{ "data": { "edges": [ { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "ChatInput", "id": "ChatInput-my2y0", "name": "message", "output_types": [ "Message" ] }, "targetHandle": { "fieldName": "input_value", "id": "ToolCallingAgent-VyZhN", "inputTypes": [ "Message" ], "type": "str" } }, "id": "reactflow__edge-ChatInput-my2y0{œdataTypeœ:œChatInputœ,œidœ:œChatInput-my2y0œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ToolCallingAgent-VyZhN{œfieldNameœ:œinput_valueœ,œidœ:œToolCallingAgent-VyZhNœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, "source": "ChatInput-my2y0", "sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-my2y0œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}", "target": "ToolCallingAgent-VyZhN", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œToolCallingAgent-VyZhNœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "NotionPageUpdate", "id": "NotionPageUpdate-DWOeO", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-NotionPageUpdate-DWOeO{œdataTypeœ:œNotionPageUpdateœ,œidœ:œNotionPageUpdate-DWOeOœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "NotionPageUpdate-DWOeO", "sourceHandle": "{œdataTypeœ:œNotionPageUpdateœ,œidœ:œNotionPageUpdate-DWOeOœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "NotionPageCreator", "id": "NotionPageCreator-Gdgtd", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-NotionPageCreator-Gdgtd{œdataTypeœ:œNotionPageCreatorœ,œidœ:œNotionPageCreator-Gdgtdœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "NotionPageCreator-Gdgtd", "sourceHandle": "{œdataTypeœ:œNotionPageCreatorœ,œidœ:œNotionPageCreator-Gdgtdœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "AddContentToPage", "id": "AddContentToPage-3iQ3m", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-AddContentToPage-3iQ3m{œdataTypeœ:œAddContentToPageœ,œidœ:œAddContentToPage-3iQ3mœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "AddContentToPage-3iQ3m", "sourceHandle": "{œdataTypeœ:œAddContentToPageœ,œidœ:œAddContentToPage-3iQ3mœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "NotionDatabaseProperties", "id": "NotionDatabaseProperties-F3Vjj", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-NotionDatabaseProperties-F3Vjj{œdataTypeœ:œNotionDatabasePropertiesœ,œidœ:œNotionDatabaseProperties-F3Vjjœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "NotionDatabaseProperties-F3Vjj", "sourceHandle": "{œdataTypeœ:œNotionDatabasePropertiesœ,œidœ:œNotionDatabaseProperties-F3Vjjœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "NotionListPages", "id": "NotionListPages-9cC7f", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-NotionListPages-9cC7f{œdataTypeœ:œNotionListPagesœ,œidœ:œNotionListPages-9cC7fœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "NotionListPages-9cC7f", "sourceHandle": "{œdataTypeœ:œNotionListPagesœ,œidœ:œNotionListPages-9cC7fœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "NotionPageContent", "id": "NotionPageContent-didQ9", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-NotionPageContent-didQ9{œdataTypeœ:œNotionPageContentœ,œidœ:œNotionPageContent-didQ9œ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "NotionPageContent-didQ9", "sourceHandle": "{œdataTypeœ:œNotionPageContentœ,œidœ:œNotionPageContent-didQ9œ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "NotionUserList", "id": "NotionUserList-4C1Rj", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-NotionUserList-4C1Rj{œdataTypeœ:œNotionUserListœ,œidœ:œNotionUserList-4C1Rjœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "NotionUserList-4C1Rj", "sourceHandle": "{œdataTypeœ:œNotionUserListœ,œidœ:œNotionUserList-4C1Rjœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "NotionSearch", "id": "NotionSearch-Qrabo", "name": "example_tool_output", "output_types": [ "Tool" ] }, "targetHandle": { "fieldName": "tools", "id": "ToolkitComponent-mfg6v", "inputTypes": [ "Tool" ], "type": "other" } }, "id": "reactflow__edge-NotionSearch-Qrabo{œdataTypeœ:œNotionSearchœ,œidœ:œNotionSearch-Qraboœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}-ToolkitComponent-mfg6v{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, "source": "NotionSearch-Qrabo", "sourceHandle": "{œdataTypeœ:œNotionSearchœ,œidœ:œNotionSearch-Qraboœ,œnameœ:œexample_tool_outputœ,œoutput_typesœ:[œToolœ]}", "target": "ToolkitComponent-mfg6v", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œToolkitComponent-mfg6vœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "OpenAIModel", "id": "OpenAIModel-gIFGV", "name": "model_output", "output_types": [ "LanguageModel" ] }, "targetHandle": { "fieldName": "llm", "id": "ToolCallingAgent-VyZhN", "inputTypes": [ "LanguageModel" ], "type": "other" } }, "id": "reactflow__edge-OpenAIModel-gIFGV{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-gIFGVœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-ToolCallingAgent-VyZhN{œfieldNameœ:œllmœ,œidœ:œToolCallingAgent-VyZhNœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", "selected": false, "source": "OpenAIModel-gIFGV", "sourceHandle": "{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-gIFGVœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}", "target": "ToolCallingAgent-VyZhN", "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œToolCallingAgent-VyZhNœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}" }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "Prompt", "id": "Prompt-S7cEu", "name": "prompt", "output_types": [ "Message" ] }, "targetHandle": { "fieldName": "system_prompt", "id": "ToolCallingAgent-VyZhN", "inputTypes": [ "Message" ], "type": "str" } }, "id": "reactflow__edge-Prompt-S7cEu{œdataTypeœ:œPromptœ,œidœ:œPrompt-S7cEuœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-ToolCallingAgent-VyZhN{œfieldNameœ:œsystem_promptœ,œidœ:œToolCallingAgent-VyZhNœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, "source": "Prompt-S7cEu", "sourceHandle": "{œdataTypeœ:œPromptœ,œidœ:œPrompt-S7cEuœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}", "target": "ToolCallingAgent-VyZhN", "targetHandle": "{œfieldNameœ:œsystem_promptœ,œidœ:œToolCallingAgent-VyZhNœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" }, { "data": { "sourceHandle": { "dataType": "Memory", "id": "Memory-4Jm4h", "name": "dataframe", "output_types": [ "DataFrame" ] }, "targetHandle": { "fieldName": "input_data", "id": "TypeConverterComponent-I2ppC", "inputTypes": [ "Message", "Data", "DataFrame" ], "type": "other" } }, "id": "xy-edge__Memory-4Jm4h{œdataTypeœ:œMemoryœ,œidœ:œMemory-4Jm4hœ,œnameœ:œdataframeœ,œoutput_typesœ:[œDataFrameœ]}-TypeConverterComponent-I2ppC{œfieldNameœ:œinput_dataœ,œidœ:œTypeConverterComponent-I2ppCœ,œinputTypesœ:[œMessageœ,œDataœ,œDataFrameœ],œtypeœ:œotherœ}", "source": "Memory-4Jm4h", "sourceHandle": "{œdataTypeœ:œMemoryœ,œidœ:œMemory-4Jm4hœ,œnameœ:œdataframeœ,œoutput_typesœ:[œDataFrameœ]}", "target": "TypeConverterComponent-I2ppC", "targetHandle": "{œfieldNameœ:œinput_dataœ,œidœ:œTypeConverterComponent-I2ppCœ,œinputTypesœ:[œMessageœ,œDataœ,œDataFrameœ],œtypeœ:œotherœ}" }, { "data": { "sourceHandle": { "dataType": "TypeConverterComponent", "id": "TypeConverterComponent-I2ppC", "name": "message_output", "output_types": [ "Message" ] }, "targetHandle": { "fieldName": "input_value", "id": "OpenAIModel-gIFGV", "inputTypes": [ "Message" ], "type": "str" } }, "id": "xy-edge__TypeConverterComponent-I2ppC{œdataTypeœ:œTypeConverterComponentœ,œidœ:œTypeConverterComponent-I2ppCœ,œnameœ:œmessage_outputœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-gIFGV{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-gIFGVœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "source": "TypeConverterComponent-I2ppC", "sourceHandle": "{œdataTypeœ:œTypeConverterComponentœ,œidœ:œTypeConverterComponent-I2ppCœ,œnameœ:œmessage_outputœ,œoutput_typesœ:[œMessageœ]}", "target": "OpenAIModel-gIFGV", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-gIFGVœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" } ], "nodes": [ { "data": { "description": "Convert markdown text to Notion blocks and append them to a Notion page.", "display_name": "Add Content to Page ", "id": "AddContentToPage-3iQ3m", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Convert markdown text to Notion blocks and append them to a Notion page.", "display_name": "Add Content to Page ", "documentation": "https://developers.notion.com/reference/patch-block-children", "edited": true, "field_order": [ "markdown_text", "block_id", "notion_secret" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "block_id": { "_input_type": "StrInput", "advanced": true, "display_name": "Page/Block ID", "dynamic": false, "info": "The ID of the page/block to add the content.", "list": false, "load_from_db": false, "name": "block_id", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "" }, "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import json\nfrom typing import Dict, Any, Union\nfrom markdown import markdown\nfrom bs4 import BeautifulSoup\nimport requests\nfrom langflow.io import Output\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, StrInput, MultilineInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\nfrom pydantic import BaseModel, Field\n\n\nclass AddContentToPage(LCToolComponent):\n display_name: str = \"Add Content to Page \"\n description: str = \"Convert markdown text to Notion blocks and append them to a Notion page.\"\n documentation: str = \"https://developers.notion.com/reference/patch-block-children\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n MultilineInput(\n name=\"markdown_text\",\n display_name=\"Markdown Text\",\n info=\"The markdown text to convert to Notion blocks.\",\n ),\n StrInput(\n name=\"block_id\",\n display_name=\"Page/Block ID\",\n info=\"The ID of the page/block to add the content.\",\n ),\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n\n class AddContentToPageSchema(BaseModel):\n markdown_text: str = Field(..., description=\"The markdown text to convert to Notion blocks.\")\n block_id: str = Field(..., description=\"The ID of the page/block to add the content.\")\n\n def run_model(self) -> Data:\n result = self._add_content_to_page(self.markdown_text, self.block_id)\n return Data(data=result, text=json.dumps(result))\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"add_content_to_notion_page\",\n description=\"Convert markdown text to Notion blocks and append them to a Notion page.\",\n func=self._add_content_to_page,\n args_schema=self.AddContentToPageSchema,\n )\n\n def _add_content_to_page(self, markdown_text: str, block_id: str) -> Union[Dict[str, Any], str]:\n try:\n html_text = markdown(markdown_text)\n soup = BeautifulSoup(html_text, \"html.parser\")\n blocks = self.process_node(soup)\n\n url = f\"https://api.notion.com/v1/blocks/{block_id}/children\"\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Content-Type\": \"application/json\",\n \"Notion-Version\": \"2022-06-28\",\n }\n\n data = {\n \"children\": blocks,\n }\n\n response = requests.patch(url, headers=headers, json=data)\n response.raise_for_status()\n\n return response.json()\n except requests.exceptions.RequestException as e:\n error_message = f\"Error: Failed to add content to Notion page. {str(e)}\"\n if hasattr(e, \"response\") and e.response is not None:\n error_message += f\" Status code: {e.response.status_code}, Response: {e.response.text}\"\n return error_message\n except Exception as e:\n return f\"Error: An unexpected error occurred while adding content to Notion page. {str(e)}\"\n\n def process_node(self, node):\n blocks = []\n if isinstance(node, str):\n text = node.strip()\n if text:\n if text.startswith(\"#\"):\n heading_level = text.count(\"#\", 0, 6)\n heading_text = text[heading_level:].strip()\n if heading_level == 1:\n blocks.append(self.create_block(\"heading_1\", heading_text))\n elif heading_level == 2:\n blocks.append(self.create_block(\"heading_2\", heading_text))\n elif heading_level == 3:\n blocks.append(self.create_block(\"heading_3\", heading_text))\n else:\n blocks.append(self.create_block(\"paragraph\", text))\n elif node.name == \"h1\":\n blocks.append(self.create_block(\"heading_1\", node.get_text(strip=True)))\n elif node.name == \"h2\":\n blocks.append(self.create_block(\"heading_2\", node.get_text(strip=True)))\n elif node.name == \"h3\":\n blocks.append(self.create_block(\"heading_3\", node.get_text(strip=True)))\n elif node.name == \"p\":\n code_node = node.find(\"code\")\n if code_node:\n code_text = code_node.get_text()\n language, code = self.extract_language_and_code(code_text)\n blocks.append(self.create_block(\"code\", code, language=language))\n elif self.is_table(str(node)):\n blocks.extend(self.process_table(node))\n else:\n blocks.append(self.create_block(\"paragraph\", node.get_text(strip=True)))\n elif node.name == \"ul\":\n blocks.extend(self.process_list(node, \"bulleted_list_item\"))\n elif node.name == \"ol\":\n blocks.extend(self.process_list(node, \"numbered_list_item\"))\n elif node.name == \"blockquote\":\n blocks.append(self.create_block(\"quote\", node.get_text(strip=True)))\n elif node.name == \"hr\":\n blocks.append(self.create_block(\"divider\", \"\"))\n elif node.name == \"img\":\n blocks.append(self.create_block(\"image\", \"\", image_url=node.get(\"src\")))\n elif node.name == \"a\":\n blocks.append(self.create_block(\"bookmark\", node.get_text(strip=True), link_url=node.get(\"href\")))\n elif node.name == \"table\":\n blocks.extend(self.process_table(node))\n\n for child in node.children:\n if isinstance(child, str):\n continue\n blocks.extend(self.process_node(child))\n\n return blocks\n\n def extract_language_and_code(self, code_text):\n lines = code_text.split(\"\\n\")\n language = lines[0].strip()\n code = \"\\n\".join(lines[1:]).strip()\n return language, code\n\n def is_code_block(self, text):\n return text.startswith(\"```\")\n\n def extract_code_block(self, text):\n lines = text.split(\"\\n\")\n language = lines[0].strip(\"`\").strip()\n code = \"\\n\".join(lines[1:]).strip(\"`\").strip()\n return language, code\n\n def is_table(self, text):\n rows = text.split(\"\\n\")\n if len(rows) < 2:\n return False\n\n has_separator = False\n for i, row in enumerate(rows):\n if \"|\" in row:\n cells = [cell.strip() for cell in row.split(\"|\")]\n cells = [cell for cell in cells if cell] # Remove empty cells\n if i == 1 and all(set(cell) <= set(\"-|\") for cell in cells):\n has_separator = True\n elif not cells:\n return False\n\n return has_separator and len(rows) >= 3\n\n def process_list(self, node, list_type):\n blocks = []\n for item in node.find_all(\"li\"):\n item_text = item.get_text(strip=True)\n checked = item_text.startswith(\"[x]\")\n is_checklist = item_text.startswith(\"[ ]\") or checked\n\n if is_checklist:\n item_text = item_text.replace(\"[x]\", \"\").replace(\"[ ]\", \"\").strip()\n blocks.append(self.create_block(\"to_do\", item_text, checked=checked))\n else:\n blocks.append(self.create_block(list_type, item_text))\n return blocks\n\n def process_table(self, node):\n blocks = []\n header_row = node.find(\"thead\").find(\"tr\") if node.find(\"thead\") else None\n body_rows = node.find(\"tbody\").find_all(\"tr\") if node.find(\"tbody\") else []\n\n if header_row or body_rows:\n table_width = max(\n len(header_row.find_all([\"th\", \"td\"])) if header_row else 0,\n max(len(row.find_all([\"th\", \"td\"])) for row in body_rows),\n )\n\n table_block = self.create_block(\"table\", \"\", table_width=table_width, has_column_header=bool(header_row))\n blocks.append(table_block)\n\n if header_row:\n header_cells = [cell.get_text(strip=True) for cell in header_row.find_all([\"th\", \"td\"])]\n header_row_block = self.create_block(\"table_row\", header_cells)\n blocks.append(header_row_block)\n\n for row in body_rows:\n cells = [cell.get_text(strip=True) for cell in row.find_all([\"th\", \"td\"])]\n row_block = self.create_block(\"table_row\", cells)\n blocks.append(row_block)\n\n return blocks\n\n def create_block(self, block_type: str, content: str, **kwargs) -> Dict[str, Any]:\n block: dict[str, Any] = {\n \"object\": \"block\",\n \"type\": block_type,\n block_type: {},\n }\n\n if block_type in [\n \"paragraph\",\n \"heading_1\",\n \"heading_2\",\n \"heading_3\",\n \"bulleted_list_item\",\n \"numbered_list_item\",\n \"quote\",\n ]:\n block[block_type][\"rich_text\"] = [\n {\n \"type\": \"text\",\n \"text\": {\n \"content\": content,\n },\n }\n ]\n elif block_type == \"to_do\":\n block[block_type][\"rich_text\"] = [\n {\n \"type\": \"text\",\n \"text\": {\n \"content\": content,\n },\n }\n ]\n block[block_type][\"checked\"] = kwargs.get(\"checked\", False)\n elif block_type == \"code\":\n block[block_type][\"rich_text\"] = [\n {\n \"type\": \"text\",\n \"text\": {\n \"content\": content,\n },\n }\n ]\n block[block_type][\"language\"] = kwargs.get(\"language\", \"plain text\")\n elif block_type == \"image\":\n block[block_type] = {\"type\": \"external\", \"external\": {\"url\": kwargs.get(\"image_url\", \"\")}}\n elif block_type == \"divider\":\n pass\n elif block_type == \"bookmark\":\n block[block_type][\"url\"] = kwargs.get(\"link_url\", \"\")\n elif block_type == \"table\":\n block[block_type][\"table_width\"] = kwargs.get(\"table_width\", 0)\n block[block_type][\"has_column_header\"] = kwargs.get(\"has_column_header\", False)\n block[block_type][\"has_row_header\"] = kwargs.get(\"has_row_header\", False)\n elif block_type == \"table_row\":\n block[block_type][\"cells\"] = [[{\"type\": \"text\", \"text\": {\"content\": cell}} for cell in content]]\n\n return block\n" }, "markdown_text": { "_input_type": "MultilineInput", "advanced": true, "display_name": "Markdown Text", "dynamic": false, "info": "The markdown text to convert to Notion blocks.", "input_types": [ "Message" ], "list": false, "load_from_db": false, "multiline": true, "name": "markdown_text", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" } } }, "type": "AddContentToPage" }, "dragging": false, "height": 330, "id": "AddContentToPage-3iQ3m", "measured": { "height": 330, "width": 320 }, "position": { "x": 1416.217259177943, "y": 1709.6205867919527 }, "positionAbsolute": { "x": 1416.217259177943, "y": 1709.6205867919527 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "description": "A component for creating Notion pages.", "display_name": "Create Page ", "id": "NotionPageCreator-Gdgtd", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "A component for creating Notion pages.", "display_name": "Create Page ", "documentation": "https://docs.langflow.org/integrations/notion/page-create", "edited": true, "field_order": [ "database_id", "notion_secret", "properties_json" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import json\nfrom typing import Dict, Any, Union\nimport requests\nfrom pydantic import BaseModel, Field\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, StrInput, MultilineInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\nfrom langflow.io import Output\n\nclass NotionPageCreator(LCToolComponent):\n display_name: str = \"Create Page \"\n description: str = \"A component for creating Notion pages.\"\n documentation: str = \"https://docs.langflow.org/integrations/notion/page-create\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n StrInput(\n name=\"database_id\",\n display_name=\"Database ID\",\n info=\"The ID of the Notion database.\",\n ),\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n MultilineInput(\n name=\"properties_json\",\n display_name=\"Properties (JSON)\",\n info=\"The properties of the new page as a JSON string.\",\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n\n class NotionPageCreatorSchema(BaseModel):\n database_id: str = Field(..., description=\"The ID of the Notion database.\")\n properties_json: str = Field(..., description=\"The properties of the new page as a JSON string.\")\n\n def run_model(self) -> Data:\n result = self._create_notion_page(self.database_id, self.properties_json)\n if isinstance(result, str):\n # An error occurred, return it as text\n return Data(text=result)\n else:\n # Success, return the created page data\n output = \"Created page properties:\\n\"\n for prop_name, prop_value in result.get(\"properties\", {}).items():\n output += f\"{prop_name}: {prop_value}\\n\"\n return Data(text=output, data=result)\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"create_notion_page\",\n description=\"Create a new page in a Notion database. IMPORTANT: Use the tool to check the Database properties for more details before using this tool.\",\n func=self._create_notion_page,\n args_schema=self.NotionPageCreatorSchema,\n )\n\n def _create_notion_page(self, database_id: str, properties_json: str) -> Union[Dict[str, Any], str]:\n if not database_id or not properties_json:\n return \"Invalid input. Please provide 'database_id' and 'properties_json'.\"\n\n try:\n properties = json.loads(properties_json)\n except json.JSONDecodeError as e:\n return f\"Invalid properties format. Please provide a valid JSON string. Error: {str(e)}\"\n\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Content-Type\": \"application/json\",\n \"Notion-Version\": \"2022-06-28\",\n }\n\n data = {\n \"parent\": {\"database_id\": database_id},\n \"properties\": properties,\n }\n\n try:\n response = requests.post(\"https://api.notion.com/v1/pages\", headers=headers, json=data)\n response.raise_for_status()\n result = response.json()\n return result\n except requests.exceptions.RequestException as e:\n error_message = f\"Failed to create Notion page. Error: {str(e)}\"\n if hasattr(e, \"response\") and e.response is not None:\n error_message += f\" Status code: {e.response.status_code}, Response: {e.response.text}\"\n return error_message\n\n def __call__(self, *args, **kwargs):\n return self._create_notion_page(*args, **kwargs)\n" }, "database_id": { "_input_type": "StrInput", "advanced": true, "display_name": "Database ID", "dynamic": false, "info": "The ID of the Notion database.", "list": false, "load_from_db": false, "name": "database_id", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" }, "properties_json": { "_input_type": "MultilineInput", "advanced": true, "display_name": "Properties (JSON)", "dynamic": false, "info": "The properties of the new page as a JSON string.", "input_types": [ "Message" ], "list": false, "load_from_db": false, "multiline": true, "name": "properties_json", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" } } }, "type": "NotionPageCreator" }, "dragging": false, "height": 302, "id": "NotionPageCreator-Gdgtd", "measured": { "height": 302, "width": 320 }, "position": { "x": 1413.9782390799146, "y": 2051.645785494985 }, "positionAbsolute": { "x": 1413.9782390799146, "y": 2051.645785494985 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "description": "Retrieve properties of a Notion database.", "display_name": "List Database Properties ", "id": "NotionDatabaseProperties-F3Vjj", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Retrieve properties of a Notion database.", "display_name": "List Database Properties ", "documentation": "https://docs.langflow.org/integrations/notion/list-database-properties", "edited": true, "field_order": [ "database_id", "notion_secret" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import requests\nfrom typing import Dict, Union\nfrom pydantic import BaseModel, Field\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, StrInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\nfrom langflow.io import Output\n\nclass NotionDatabaseProperties(LCToolComponent):\n display_name: str = \"List Database Properties \"\n description: str = \"Retrieve properties of a Notion database.\"\n documentation: str = \"https://docs.langflow.org/integrations/notion/list-database-properties\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n StrInput(\n name=\"database_id\",\n display_name=\"Database ID\",\n info=\"The ID of the Notion database.\",\n ),\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n\n class NotionDatabasePropertiesSchema(BaseModel):\n database_id: str = Field(..., description=\"The ID of the Notion database.\")\n\n def run_model(self) -> Data:\n result = self._fetch_database_properties(self.database_id)\n if isinstance(result, str):\n # An error occurred, return it as text\n return Data(text=result)\n else:\n # Success, return the properties\n return Data(text=str(result), data=result)\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"notion_database_properties\",\n description=\"Retrieve properties of a Notion database. Input should include the database ID.\",\n func=self._fetch_database_properties,\n args_schema=self.NotionDatabasePropertiesSchema,\n )\n\n def _fetch_database_properties(self, database_id: str) -> Union[Dict, str]:\n url = f\"https://api.notion.com/v1/databases/{database_id}\"\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Notion-Version\": \"2022-06-28\", # Use the latest supported version\n }\n try:\n response = requests.get(url, headers=headers)\n response.raise_for_status()\n data = response.json()\n properties = data.get(\"properties\", {})\n return properties\n except requests.exceptions.RequestException as e:\n return f\"Error fetching Notion database properties: {str(e)}\"\n except ValueError as e:\n return f\"Error parsing Notion API response: {str(e)}\"\n except Exception as e:\n return f\"An unexpected error occurred: {str(e)}\"\n" }, "database_id": { "_input_type": "StrInput", "advanced": true, "display_name": "Database ID", "dynamic": false, "info": "The ID of the Notion database.", "list": false, "load_from_db": false, "name": "database_id", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" } } }, "type": "NotionDatabaseProperties" }, "dragging": false, "height": 302, "id": "NotionDatabaseProperties-F3Vjj", "measured": { "height": 302, "width": 320 }, "position": { "x": 1004.5753613670959, "y": 1713.914531491452 }, "positionAbsolute": { "x": 1004.5753613670959, "y": 1713.914531491452 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "description": "Query a Notion database with filtering and sorting. The input should be a JSON string containing the 'filter' and 'sorts' objects. Example input:\n{\"filter\": {\"property\": \"Status\", \"select\": {\"equals\": \"Done\"}}, \"sorts\": [{\"timestamp\": \"created_time\", \"direction\": \"descending\"}]}", "display_name": "List Pages ", "id": "NotionListPages-9cC7f", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Query a Notion database with filtering and sorting. The input should be a JSON string containing the 'filter' and 'sorts' objects. Example input:\n{\"filter\": {\"property\": \"Status\", \"select\": {\"equals\": \"Done\"}}, \"sorts\": [{\"timestamp\": \"created_time\", \"direction\": \"descending\"}]}", "display_name": "List Pages ", "documentation": "https://docs.langflow.org/integrations/notion/list-pages", "edited": true, "field_order": [ "notion_secret", "database_id", "query_json" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import requests\nimport json\nfrom typing import Dict, Any, List, Optional\nfrom pydantic import BaseModel, Field\nfrom langflow.io import Output\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, StrInput, MultilineInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\n\n\nclass NotionListPages(LCToolComponent):\n display_name: str = \"List Pages \"\n description: str = (\n \"Query a Notion database with filtering and sorting. \"\n \"The input should be a JSON string containing the 'filter' and 'sorts' objects. \"\n \"Example input:\\n\"\n '{\"filter\": {\"property\": \"Status\", \"select\": {\"equals\": \"Done\"}}, \"sorts\": [{\"timestamp\": \"created_time\", \"direction\": \"descending\"}]}'\n )\n documentation: str = \"https://docs.langflow.org/integrations/notion/list-pages\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n StrInput(\n name=\"database_id\",\n display_name=\"Database ID\",\n info=\"The ID of the Notion database to query.\",\n ),\n MultilineInput(\n name=\"query_json\",\n display_name=\"Database query (JSON)\",\n info=\"A JSON string containing the filters and sorts that will be used for querying the database. Leave empty for no filters or sorts.\",\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n class NotionListPagesSchema(BaseModel):\n database_id: str = Field(..., description=\"The ID of the Notion database to query.\")\n query_json: Optional[str] = Field(\n default=\"\",\n description=\"A JSON string containing the filters and sorts for querying the database. Leave empty for no filters or sorts.\",\n )\n\n def run_model(self) -> List[Data]:\n result = self._query_notion_database(self.database_id, self.query_json)\n\n if isinstance(result, str):\n # An error occurred, return it as a single record\n return [Data(text=result)]\n\n records = []\n combined_text = f\"Pages found: {len(result)}\\n\\n\"\n\n for page in result:\n page_data = {\n \"id\": page[\"id\"],\n \"url\": page[\"url\"],\n \"created_time\": page[\"created_time\"],\n \"last_edited_time\": page[\"last_edited_time\"],\n \"properties\": page[\"properties\"],\n }\n\n text = (\n f\"id: {page['id']}\\n\"\n f\"url: {page['url']}\\n\"\n f\"created_time: {page['created_time']}\\n\"\n f\"last_edited_time: {page['last_edited_time']}\\n\"\n f\"properties: {json.dumps(page['properties'], indent=2)}\\n\\n\"\n )\n\n combined_text += text\n records.append(Data(text=text, **page_data))\n\n self.status = records\n return records\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"notion_list_pages\",\n description=self.description,\n func=self._query_notion_database,\n args_schema=self.NotionListPagesSchema,\n )\n\n def _query_notion_database(self, database_id: str, query_json: Optional[str] = None) -> List[Dict[str, Any]] | str:\n url = f\"https://api.notion.com/v1/databases/{database_id}/query\"\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Content-Type\": \"application/json\",\n \"Notion-Version\": \"2022-06-28\",\n }\n\n query_payload = {}\n if query_json and query_json.strip():\n try:\n query_payload = json.loads(query_json)\n except json.JSONDecodeError as e:\n return f\"Invalid JSON format for query: {str(e)}\"\n\n try:\n response = requests.post(url, headers=headers, json=query_payload)\n response.raise_for_status()\n results = response.json()\n return results[\"results\"]\n except requests.exceptions.RequestException as e:\n return f\"Error querying Notion database: {str(e)}\"\n except KeyError:\n return \"Unexpected response format from Notion API\"\n except Exception as e:\n return f\"An unexpected error occurred: {str(e)}\"\n" }, "database_id": { "_input_type": "StrInput", "advanced": true, "display_name": "Database ID", "dynamic": false, "info": "The ID of the Notion database to query.", "list": false, "load_from_db": false, "name": "database_id", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" }, "query_json": { "_input_type": "MultilineInput", "advanced": true, "display_name": "Database query (JSON)", "dynamic": false, "info": "A JSON string containing the filters and sorts that will be used for querying the database. Leave empty for no filters or sorts.", "input_types": [ "Message" ], "list": false, "load_from_db": false, "multiline": true, "name": "query_json", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" } } }, "type": "NotionListPages" }, "dragging": false, "height": 470, "id": "NotionListPages-9cC7f", "measured": { "height": 470, "width": 320 }, "position": { "x": 1006.1848442547046, "y": 2022.7880909242833 }, "positionAbsolute": { "x": 1006.1848442547046, "y": 2022.7880909242833 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "description": "Retrieve users from Notion.", "display_name": "List Users ", "id": "NotionUserList-4C1Rj", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Retrieve users from Notion.", "display_name": "List Users ", "documentation": "https://docs.langflow.org/integrations/notion/list-users", "edited": true, "field_order": [ "notion_secret" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import requests\nfrom typing import List, Dict\nfrom pydantic import BaseModel\nfrom langflow.io import Output\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\n\n\nclass NotionUserList(LCToolComponent):\n display_name = \"List Users \"\n description = \"Retrieve users from Notion.\"\n documentation = \"https://docs.langflow.org/integrations/notion/list-users\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n\n class NotionUserListSchema(BaseModel):\n pass\n\n def run_model(self) -> List[Data]:\n users = self._list_users()\n records = []\n combined_text = \"\"\n\n for user in users:\n output = \"User:\\n\"\n for key, value in user.items():\n output += f\"{key.replace('_', ' ').title()}: {value}\\n\"\n output += \"________________________\\n\"\n\n combined_text += output\n records.append(Data(text=output, data=user))\n\n self.status = records\n return records\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"notion_list_users\",\n description=\"Retrieve users from Notion.\",\n func=self._list_users,\n args_schema=self.NotionUserListSchema,\n )\n\n def _list_users(self) -> List[Dict]:\n url = \"https://api.notion.com/v1/users\"\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Notion-Version\": \"2022-06-28\",\n }\n\n response = requests.get(url, headers=headers)\n response.raise_for_status()\n\n data = response.json()\n results = data[\"results\"]\n\n users = []\n for user in results:\n user_data = {\n \"id\": user[\"id\"],\n \"type\": user[\"type\"],\n \"name\": user.get(\"name\", \"\"),\n \"avatar_url\": user.get(\"avatar_url\", \"\"),\n }\n users.append(user_data)\n\n return users\n" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" } } }, "type": "NotionUserList" }, "dragging": false, "height": 302, "id": "NotionUserList-4C1Rj", "measured": { "height": 302, "width": 320 }, "position": { "x": 2260.15497405973, "y": 1717.4551881467207 }, "positionAbsolute": { "x": 2260.15497405973, "y": 1717.4551881467207 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "description": "Retrieve the content of a Notion page as plain text.", "display_name": "Page Content Viewer ", "id": "NotionPageContent-didQ9", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Retrieve the content of a Notion page as plain text.", "display_name": "Page Content Viewer ", "documentation": "https://docs.langflow.org/integrations/notion/page-content-viewer", "edited": true, "field_order": [ "page_id", "notion_secret" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import requests\nfrom pydantic import BaseModel, Field\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, StrInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\nfrom langflow.io import Output\n\nclass NotionPageContent(LCToolComponent):\n display_name = \"Page Content Viewer \"\n description = \"Retrieve the content of a Notion page as plain text.\"\n documentation = \"https://docs.langflow.org/integrations/notion/page-content-viewer\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n StrInput(\n name=\"page_id\",\n display_name=\"Page ID\",\n info=\"The ID of the Notion page to retrieve.\",\n ),\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n\n class NotionPageContentSchema(BaseModel):\n page_id: str = Field(..., description=\"The ID of the Notion page to retrieve.\")\n\n def run_model(self) -> Data:\n result = self._retrieve_page_content(self.page_id)\n if isinstance(result, str) and result.startswith(\"Error:\"):\n # An error occurred, return it as text\n return Data(text=result)\n else:\n # Success, return the content\n return Data(text=result, data={\"content\": result})\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"notion_page_content\",\n description=\"Retrieve the content of a Notion page as plain text.\",\n func=self._retrieve_page_content,\n args_schema=self.NotionPageContentSchema,\n )\n\n def _retrieve_page_content(self, page_id: str) -> str:\n blocks_url = f\"https://api.notion.com/v1/blocks/{page_id}/children?page_size=100\"\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Notion-Version\": \"2022-06-28\",\n }\n try:\n blocks_response = requests.get(blocks_url, headers=headers)\n blocks_response.raise_for_status()\n blocks_data = blocks_response.json()\n return self.parse_blocks(blocks_data.get(\"results\", []))\n except requests.exceptions.RequestException as e:\n error_message = f\"Error: Failed to retrieve Notion page content. {str(e)}\"\n if hasattr(e, \"response\") and e.response is not None:\n error_message += f\" Status code: {e.response.status_code}, Response: {e.response.text}\"\n return error_message\n except Exception as e:\n return f\"Error: An unexpected error occurred while retrieving Notion page content. {str(e)}\"\n\n def parse_blocks(self, blocks: list) -> str:\n content = \"\"\n for block in blocks:\n block_type = block.get(\"type\")\n if block_type in [\"paragraph\", \"heading_1\", \"heading_2\", \"heading_3\", \"quote\"]:\n content += self.parse_rich_text(block[block_type].get(\"rich_text\", [])) + \"\\n\\n\"\n elif block_type in [\"bulleted_list_item\", \"numbered_list_item\"]:\n content += self.parse_rich_text(block[block_type].get(\"rich_text\", [])) + \"\\n\"\n elif block_type == \"to_do\":\n content += self.parse_rich_text(block[\"to_do\"].get(\"rich_text\", [])) + \"\\n\"\n elif block_type == \"code\":\n content += self.parse_rich_text(block[\"code\"].get(\"rich_text\", [])) + \"\\n\\n\"\n elif block_type == \"image\":\n content += f\"[Image: {block['image'].get('external', {}).get('url', 'No URL')}]\\n\\n\"\n elif block_type == \"divider\":\n content += \"---\\n\\n\"\n return content.strip()\n\n def parse_rich_text(self, rich_text: list) -> str:\n return \"\".join(segment.get(\"plain_text\", \"\") for segment in rich_text)\n\n def __call__(self, *args, **kwargs):\n return self._retrieve_page_content(*args, **kwargs)\n" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" }, "page_id": { "_input_type": "StrInput", "advanced": true, "display_name": "Page ID", "dynamic": false, "info": "The ID of the Notion page to retrieve.", "list": false, "load_from_db": false, "name": "page_id", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "" } } }, "type": "NotionPageContent" }, "dragging": false, "height": 330, "id": "NotionPageContent-didQ9", "measured": { "height": 330, "width": 320 }, "position": { "x": 1826.4242329724448, "y": 1715.6365113286927 }, "positionAbsolute": { "x": 1826.4242329724448, "y": 1715.6365113286927 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "description": "Searches all pages and databases that have been shared with an integration.", "display_name": "Search ", "id": "NotionSearch-Qrabo", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Searches all pages and databases that have been shared with an integration. The search field can be an empty value to show all values from that search", "display_name": "Search ", "documentation": "https://docs.langflow.org/integrations/notion/search", "edited": true, "field_order": [ "notion_secret", "query", "filter_value", "sort_direction" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import requests\nfrom typing import Dict, Any, List\nfrom pydantic import BaseModel, Field\nfrom langflow.io import Output\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, StrInput, DropdownInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\n\n\nclass NotionSearch(LCToolComponent):\n display_name: str = \"Search \"\n description: str = \"Searches all pages and databases that have been shared with an integration. The search field can be an empty value to show all values from that search\"\n documentation: str = \"https://docs.langflow.org/integrations/notion/search\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n StrInput(\n name=\"query\",\n display_name=\"Search Query\",\n info=\"The text that the API compares page and database titles against.\",\n ),\n DropdownInput(\n name=\"filter_value\",\n display_name=\"Filter Type\",\n info=\"Limits the results to either only pages or only databases.\",\n options=[\"page\", \"database\"],\n value=\"page\",\n ),\n DropdownInput(\n name=\"sort_direction\",\n display_name=\"Sort Direction\",\n info=\"The direction to sort the results.\",\n options=[\"ascending\", \"descending\"],\n value=\"descending\",\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n\n class NotionSearchSchema(BaseModel):\n query: str = Field(..., description=\"The search query text.\")\n filter_value: str = Field(default=\"page\", description=\"Filter type: 'page' or 'database'.\")\n sort_direction: str = Field(default=\"descending\", description=\"Sort direction: 'ascending' or 'descending'.\")\n\n def run_model(self) -> List[Data]:\n results = self._search_notion(self.query, self.filter_value, self.sort_direction)\n records = []\n combined_text = f\"Results found: {len(results)}\\n\\n\"\n\n for result in results:\n result_data = {\n \"id\": result[\"id\"],\n \"type\": result[\"object\"],\n \"last_edited_time\": result[\"last_edited_time\"],\n }\n\n if result[\"object\"] == \"page\":\n result_data[\"title_or_url\"] = result[\"url\"]\n text = f\"id: {result['id']}\\ntitle_or_url: {result['url']}\\n\"\n elif result[\"object\"] == \"database\":\n if \"title\" in result and isinstance(result[\"title\"], list) and len(result[\"title\"]) > 0:\n result_data[\"title_or_url\"] = result[\"title\"][0][\"plain_text\"]\n text = f\"id: {result['id']}\\ntitle_or_url: {result['title'][0]['plain_text']}\\n\"\n else:\n result_data[\"title_or_url\"] = \"N/A\"\n text = f\"id: {result['id']}\\ntitle_or_url: N/A\\n\"\n\n text += f\"type: {result['object']}\\nlast_edited_time: {result['last_edited_time']}\\n\\n\"\n combined_text += text\n records.append(Data(text=text, data=result_data))\n\n self.status = records\n return records\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"notion_search\",\n description=\"Search Notion pages and databases. Input should include the search query and optionally filter type and sort direction.\",\n func=self._search_notion,\n args_schema=self.NotionSearchSchema,\n )\n\n def _search_notion(\n self, query: str, filter_value: str = \"page\", sort_direction: str = \"descending\"\n ) -> List[Dict[str, Any]]:\n url = \"https://api.notion.com/v1/search\"\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Content-Type\": \"application/json\",\n \"Notion-Version\": \"2022-06-28\",\n }\n\n data = {\n \"query\": query,\n \"filter\": {\"value\": filter_value, \"property\": \"object\"},\n \"sort\": {\"direction\": sort_direction, \"timestamp\": \"last_edited_time\"},\n }\n\n response = requests.post(url, headers=headers, json=data)\n response.raise_for_status()\n\n results = response.json()\n return results[\"results\"]\n" }, "filter_value": { "_input_type": "DropdownInput", "advanced": true, "combobox": false, "display_name": "Filter Type", "dynamic": false, "info": "Limits the results to either only pages or only databases.", "name": "filter_value", "options": [ "page", "database" ], "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "page" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" }, "query": { "_input_type": "StrInput", "advanced": true, "display_name": "Search Query", "dynamic": false, "info": "The text that the API compares page and database titles against.", "list": false, "load_from_db": false, "name": "query", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "" }, "sort_direction": { "_input_type": "DropdownInput", "advanced": true, "combobox": false, "display_name": "Sort Direction", "dynamic": false, "info": "The direction to sort the results.", "name": "sort_direction", "options": [ "ascending", "descending" ], "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "descending" } } }, "type": "NotionSearch" }, "dragging": false, "height": 386, "id": "NotionSearch-Qrabo", "measured": { "height": 386, "width": 320 }, "position": { "x": 2258.1166047519732, "y": 2034.3959294952945 }, "positionAbsolute": { "x": 2258.1166047519732, "y": 2034.3959294952945 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "description": "Update the properties of a Notion page.", "display_name": "Update Page Property ", "id": "NotionPageUpdate-DWOeO", "node": { "base_classes": [ "Data", "Tool" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Update the properties of a Notion page.", "display_name": "Update Page Property ", "documentation": "https://docs.langflow.org/integrations/notion/page-update", "edited": true, "field_order": [ "page_id", "properties", "notion_secret" ], "frozen": false, "icon": "NotionDirectoryLoader", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Data", "hidden": true, "method": "run_model", "name": "example_output", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool", "method": "build_tool", "name": "example_tool_output", "selected": "Tool", "types": [ "Tool" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "import json\nimport requests\nfrom typing import Dict, Any, Union\nfrom pydantic import BaseModel, Field\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, StrInput, MultilineInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\nfrom langchain.tools import StructuredTool\nfrom loguru import logger\nfrom langflow.io import Output\n\nclass NotionPageUpdate(LCToolComponent):\n display_name: str = \"Update Page Property \"\n description: str = \"Update the properties of a Notion page.\"\n documentation: str = \"https://docs.langflow.org/integrations/notion/page-update\"\n icon = \"NotionDirectoryLoader\"\n\n inputs = [\n StrInput(\n name=\"page_id\",\n display_name=\"Page ID\",\n info=\"The ID of the Notion page to update.\",\n ),\n MultilineInput(\n name=\"properties\",\n display_name=\"Properties\",\n info=\"The properties to update on the page (as a JSON string or a dictionary).\",\n ),\n SecretStrInput(\n name=\"notion_secret\",\n display_name=\"Notion Secret\",\n info=\"The Notion integration token.\",\n required=True,\n ),\n ]\n outputs = [\n Output(name=\"example_output\", display_name=\"Data\", method=\"run_model\"),\n Output(name=\"example_tool_output\", display_name=\"Tool\", method=\"build_tool\"),\n ]\n\n class NotionPageUpdateSchema(BaseModel):\n page_id: str = Field(..., description=\"The ID of the Notion page to update.\")\n properties: Union[str, Dict[str, Any]] = Field(\n ..., description=\"The properties to update on the page (as a JSON string or a dictionary).\"\n )\n\n def run_model(self) -> Data:\n result = self._update_notion_page(self.page_id, self.properties)\n if isinstance(result, str):\n # An error occurred, return it as text\n return Data(text=result)\n else:\n # Success, return the updated page data\n output = \"Updated page properties:\\n\"\n for prop_name, prop_value in result.get(\"properties\", {}).items():\n output += f\"{prop_name}: {prop_value}\\n\"\n return Data(text=output, data=result)\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"update_notion_page\",\n description=\"Update the properties of a Notion page. IMPORTANT: Use the tool to check the Database properties for more details before using this tool.\",\n func=self._update_notion_page,\n args_schema=self.NotionPageUpdateSchema,\n )\n\n def _update_notion_page(self, page_id: str, properties: Union[str, Dict[str, Any]]) -> Union[Dict[str, Any], str]:\n url = f\"https://api.notion.com/v1/pages/{page_id}\"\n headers = {\n \"Authorization\": f\"Bearer {self.notion_secret}\",\n \"Content-Type\": \"application/json\",\n \"Notion-Version\": \"2022-06-28\", # Use the latest supported version\n }\n\n # Parse properties if it's a string\n if isinstance(properties, str):\n try:\n parsed_properties = json.loads(properties)\n except json.JSONDecodeError as e:\n error_message = f\"Invalid JSON format for properties: {str(e)}\"\n logger.error(error_message)\n return error_message\n\n else:\n parsed_properties = properties\n\n data = {\"properties\": parsed_properties}\n\n try:\n logger.info(f\"Sending request to Notion API: URL: {url}, Data: {json.dumps(data)}\")\n response = requests.patch(url, headers=headers, json=data)\n response.raise_for_status()\n updated_page = response.json()\n\n logger.info(f\"Successfully updated Notion page. Response: {json.dumps(updated_page)}\")\n return updated_page\n except requests.exceptions.HTTPError as e:\n error_message = f\"HTTP Error occurred: {str(e)}\"\n if e.response is not None:\n error_message += f\"\\nStatus code: {e.response.status_code}\"\n error_message += f\"\\nResponse body: {e.response.text}\"\n logger.error(error_message)\n return error_message\n except requests.exceptions.RequestException as e:\n error_message = f\"An error occurred while making the request: {str(e)}\"\n logger.error(error_message)\n return error_message\n except Exception as e:\n error_message = f\"An unexpected error occurred: {str(e)}\"\n logger.error(error_message)\n return error_message\n\n def __call__(self, *args, **kwargs):\n return self._update_notion_page(*args, **kwargs)\n" }, "notion_secret": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "Notion Secret", "dynamic": false, "info": "The Notion integration token.", "input_types": [ "Message" ], "load_from_db": false, "name": "notion_secret", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" }, "page_id": { "_input_type": "StrInput", "advanced": true, "display_name": "Page ID", "dynamic": false, "info": "The ID of the Notion page to update.", "list": false, "load_from_db": false, "name": "page_id", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "" }, "properties": { "_input_type": "MultilineInput", "advanced": true, "display_name": "Properties", "dynamic": false, "info": "The properties to update on the page (as a JSON string or a dictionary).", "input_types": [ "Message" ], "list": false, "load_from_db": false, "multiline": true, "name": "properties", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" } } }, "type": "NotionPageUpdate" }, "dragging": false, "height": 302, "id": "NotionPageUpdate-DWOeO", "measured": { "height": 302, "width": 320 }, "position": { "x": 1827.0574354713603, "y": 2055.9948126656136 }, "positionAbsolute": { "x": 1827.0574354713603, "y": 2055.9948126656136 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "ToolCallingAgent-VyZhN", "node": { "base_classes": [ "AgentExecutor", "Message" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "An agent designed to utilize various tools seamlessly within workflows.", "display_name": "Tool Calling Agent", "documentation": "", "edited": false, "field_order": [ "tools", "input_value", "handle_parsing_errors", "verbose", "max_iterations", "agent_description", "llm", "system_prompt", "chat_history" ], "frozen": false, "icon": "LangChain", "legacy": false, "metadata": {}, "minimized": false, "output_types": [], "outputs": [ { "allows_loop": false, "cache": true, "display_name": "Agent", "group_outputs": false, "hidden": true, "method": "build_agent", "name": "agent", "options": null, "required_inputs": [], "selected": "AgentExecutor", "tool_mode": false, "types": [ "AgentExecutor" ], "value": "__UNDEFINED__" }, { "allows_loop": false, "cache": true, "display_name": "Response", "group_outputs": false, "method": "message_response", "name": "response", "options": null, "required_inputs": [], "selected": "Message", "tool_mode": true, "types": [ "Message" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "agent_description": { "_input_type": "MultilineInput", "advanced": true, "copy_field": false, "display_name": "Agent Description [Deprecated]", "dynamic": false, "info": "The description of the agent. This is only used when in Tool Mode. Defaults to 'A helpful assistant with access to the following tools:' and tools are added dynamically. This feature is deprecated and will be removed in future versions.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "multiline": true, "name": "agent_description", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "A helpful assistant with access to the following tools:" }, "chat_history": { "_input_type": "DataInput", "advanced": false, "display_name": "Chat Memory", "dynamic": false, "info": "This input stores the chat history, allowing the agent to remember previous conversations.", "input_types": [ "Data" ], "list": true, "list_add_label": "Add More", "name": "chat_history", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "other", "value": "" }, "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from langchain.agents import create_tool_calling_agent\nfrom langchain_core.prompts import ChatPromptTemplate\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.inputs import MessageTextInput\nfrom langflow.inputs.inputs import DataInput, HandleInput\nfrom langflow.schema import Data\n\n\nclass ToolCallingAgentComponent(LCToolsAgentComponent):\n display_name: str = \"Tool Calling Agent\"\n description: str = \"An agent designed to utilize various tools seamlessly within workflows.\"\n icon = \"LangChain\"\n name = \"ToolCallingAgent\"\n\n inputs = [\n *LCToolsAgentComponent._base_inputs,\n HandleInput(\n name=\"llm\",\n display_name=\"Language Model\",\n input_types=[\"LanguageModel\"],\n required=True,\n info=\"Language model that the agent utilizes to perform tasks effectively.\",\n ),\n MessageTextInput(\n name=\"system_prompt\",\n display_name=\"System Prompt\",\n info=\"System prompt to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n ),\n DataInput(\n name=\"chat_history\",\n display_name=\"Chat Memory\",\n is_list=True,\n advanced=True,\n info=\"This input stores the chat history, allowing the agent to remember previous conversations.\",\n ),\n ]\n\n def get_chat_history_data(self) -> list[Data] | None:\n return self.chat_history\n\n def create_agent_runnable(self):\n messages = [\n (\"system\", \"{system_prompt}\"),\n (\"placeholder\", \"{chat_history}\"),\n (\"human\", \"{input}\"),\n (\"placeholder\", \"{agent_scratchpad}\"),\n ]\n prompt = ChatPromptTemplate.from_messages(messages)\n self.validate_tool_names()\n try:\n return create_tool_calling_agent(self.llm, self.tools or [], prompt)\n except NotImplementedError as e:\n message = f\"{self.display_name} does not support tool calling. Please try using a compatible model.\"\n raise NotImplementedError(message) from e\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", "advanced": true, "display_name": "Handle Parse Errors", "dynamic": false, "info": "Should the Agent fix errors when reading user input for better processing?", "list": false, "list_add_label": "Add More", "name": "handle_parsing_errors", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": true }, "input_value": { "_input_type": "MessageTextInput", "advanced": false, "display_name": "Input", "dynamic": false, "info": "The input provided by the user for the agent to process.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "input_value", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "llm": { "_input_type": "HandleInput", "advanced": false, "display_name": "Language Model", "dynamic": false, "info": "Language model that the agent utilizes to perform tasks effectively.", "input_types": [ "LanguageModel" ], "list": false, "list_add_label": "Add More", "name": "llm", "placeholder": "", "required": true, "show": true, "title_case": false, "trace_as_metadata": true, "type": "other", "value": "" }, "max_iterations": { "_input_type": "IntInput", "advanced": true, "display_name": "Max Iterations", "dynamic": false, "info": "The maximum number of attempts the agent can make to complete its task before it stops.", "list": false, "list_add_label": "Add More", "name": "max_iterations", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "int", "value": 15 }, "system_prompt": { "_input_type": "MessageTextInput", "advanced": false, "display_name": "System Prompt", "dynamic": false, "info": "System prompt to guide the agent's behavior.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "system_prompt", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "tools": { "_input_type": "HandleInput", "advanced": false, "display_name": "Tools", "dynamic": false, "info": "These are the tools that the agent can use to help with tasks.", "input_types": [ "Tool" ], "list": true, "list_add_label": "Add More", "name": "tools", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "other", "value": "" }, "verbose": { "_input_type": "BoolInput", "advanced": true, "display_name": "Verbose", "dynamic": false, "info": "", "list": false, "list_add_label": "Add More", "name": "verbose", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": true } }, "tool_mode": false }, "type": "ToolCallingAgent" }, "dragging": false, "height": 532, "id": "ToolCallingAgent-VyZhN", "measured": { "height": 532, "width": 320 }, "position": { "x": 2186.0530739759893, "y": 612.1744804997304 }, "positionAbsolute": { "x": 2186.0530739759893, "y": 612.1744804997304 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "ChatOutput-jessc", "node": { "base_classes": [ "Message" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Display a chat message in the Playground.", "display_name": "Chat Output", "documentation": "", "edited": false, "field_order": [ "input_value", "should_store_message", "sender", "sender_name", "session_id", "data_template", "background_color", "chat_icon", "text_color", "clean_data" ], "frozen": false, "icon": "MessagesSquare", "legacy": false, "metadata": {}, "minimized": true, "output_types": [], "outputs": [ { "allows_loop": false, "cache": true, "display_name": "Output Message", "group_outputs": false, "method": "message_response", "name": "message", "options": null, "required_inputs": null, "selected": "Message", "tool_mode": true, "types": [ "Message" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "background_color": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Background Color", "dynamic": false, "info": "The background color of the icon.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "background_color", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "chat_icon": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Icon", "dynamic": false, "info": "The icon of the message.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "chat_icon", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "clean_data": { "_input_type": "BoolInput", "advanced": true, "display_name": "Basic Clean Data", "dynamic": false, "info": "Whether to clean the data", "list": false, "list_add_label": "Add More", "name": "clean_data", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": true }, "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from collections.abc import Generator\nfrom typing import Any\n\nimport orjson\nfrom fastapi.encoders import jsonable_encoder\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.helpers.data import safe_convert\nfrom langflow.inputs import BoolInput\nfrom langflow.inputs.inputs import HandleInput\nfrom langflow.io import DropdownInput, MessageTextInput, Output\nfrom langflow.schema.data import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.message import Message\nfrom langflow.schema.properties import Source\nfrom langflow.utils.constants import (\n MESSAGE_SENDER_AI,\n MESSAGE_SENDER_NAME_AI,\n MESSAGE_SENDER_USER,\n)\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"MessagesSquare\"\n name = \"ChatOutput\"\n minimized = True\n\n inputs = [\n HandleInput(\n name=\"input_value\",\n display_name=\"Inputs\",\n info=\"Message to be passed as output.\",\n input_types=[\"Data\", \"DataFrame\", \"Message\"],\n required=True,\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_AI,\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_AI,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n MessageTextInput(\n name=\"background_color\",\n display_name=\"Background Color\",\n info=\"The background color of the icon.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"chat_icon\",\n display_name=\"Icon\",\n info=\"The icon of the message.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"text_color\",\n display_name=\"Text Color\",\n info=\"The text color of the name\",\n advanced=True,\n ),\n BoolInput(\n name=\"clean_data\",\n display_name=\"Basic Clean Data\",\n value=True,\n info=\"Whether to clean the data\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(\n display_name=\"Output Message\",\n name=\"message\",\n method=\"message_response\",\n ),\n ]\n\n def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:\n source_dict = {}\n if id_:\n source_dict[\"id\"] = id_\n if display_name:\n source_dict[\"display_name\"] = display_name\n if source:\n # Handle case where source is a ChatOpenAI object\n if hasattr(source, \"model_name\"):\n source_dict[\"source\"] = source.model_name\n elif hasattr(source, \"model\"):\n source_dict[\"source\"] = str(source.model)\n else:\n source_dict[\"source\"] = str(source)\n return Source(**source_dict)\n\n async def message_response(self) -> Message:\n # First convert the input to string if needed\n text = self.convert_to_string()\n\n # Get source properties\n source, icon, display_name, source_id = self.get_properties_from_source_component()\n background_color = self.background_color\n text_color = self.text_color\n if self.chat_icon:\n icon = self.chat_icon\n\n # Create or use existing Message object\n if isinstance(self.input_value, Message):\n message = self.input_value\n # Update message properties\n message.text = text\n else:\n message = Message(text=text)\n\n # Set message properties\n message.sender = self.sender\n message.sender_name = self.sender_name\n message.session_id = self.session_id\n message.flow_id = self.graph.flow_id if hasattr(self, \"graph\") else None\n message.properties.source = self._build_source(source_id, display_name, source)\n message.properties.icon = icon\n message.properties.background_color = background_color\n message.properties.text_color = text_color\n\n # Store message if needed\n if self.session_id and self.should_store_message:\n stored_message = await self.send_message(message)\n self.message.value = stored_message\n message = stored_message\n\n self.status = message\n return message\n\n def _serialize_data(self, data: Data) -> str:\n \"\"\"Serialize Data object to JSON string.\"\"\"\n # Convert data.data to JSON-serializable format\n serializable_data = jsonable_encoder(data.data)\n # Serialize with orjson, enabling pretty printing with indentation\n json_bytes = orjson.dumps(serializable_data, option=orjson.OPT_INDENT_2)\n # Convert bytes to string and wrap in Markdown code blocks\n return \"```json\\n\" + json_bytes.decode(\"utf-8\") + \"\\n```\"\n\n def _validate_input(self) -> None:\n \"\"\"Validate the input data and raise ValueError if invalid.\"\"\"\n if self.input_value is None:\n msg = \"Input data cannot be None\"\n raise ValueError(msg)\n if isinstance(self.input_value, list) and not all(\n isinstance(item, Message | Data | DataFrame | str) for item in self.input_value\n ):\n invalid_types = [\n type(item).__name__\n for item in self.input_value\n if not isinstance(item, Message | Data | DataFrame | str)\n ]\n msg = f\"Expected Data or DataFrame or Message or str, got {invalid_types}\"\n raise TypeError(msg)\n if not isinstance(\n self.input_value,\n Message | Data | DataFrame | str | list | Generator | type(None),\n ):\n type_name = type(self.input_value).__name__\n msg = f\"Expected Data or DataFrame or Message or str, Generator or None, got {type_name}\"\n raise TypeError(msg)\n\n def convert_to_string(self) -> str | Generator[Any, None, None]:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n self._validate_input()\n if isinstance(self.input_value, list):\n return \"\\n\".join([safe_convert(item, clean_data=self.clean_data) for item in self.input_value])\n if isinstance(self.input_value, Generator):\n return self.input_value\n return safe_convert(self.input_value)\n" }, "data_template": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Data Template", "dynamic": false, "info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "data_template", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "{text}" }, "input_value": { "_input_type": "HandleInput", "advanced": false, "display_name": "Inputs", "dynamic": false, "info": "Message to be passed as output.", "input_types": [ "Data", "DataFrame", "Message" ], "list": false, "list_add_label": "Add More", "name": "input_value", "placeholder": "", "required": true, "show": true, "title_case": false, "trace_as_metadata": true, "type": "other", "value": "" }, "sender": { "_input_type": "DropdownInput", "advanced": true, "combobox": false, "dialog_inputs": {}, "display_name": "Sender Type", "dynamic": false, "info": "Type of sender.", "name": "sender", "options": [ "Machine", "User" ], "options_metadata": [], "placeholder": "", "required": false, "show": true, "title_case": false, "toggle": false, "tool_mode": false, "trace_as_metadata": true, "type": "str", "value": "Machine" }, "sender_name": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Sender Name", "dynamic": false, "info": "Name of the sender.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "sender_name", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "AI" }, "session_id": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Session ID", "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "session_id", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "should_store_message": { "_input_type": "BoolInput", "advanced": true, "display_name": "Store Messages", "dynamic": false, "info": "Store the message in the history.", "list": false, "list_add_label": "Add More", "name": "should_store_message", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": true }, "text_color": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Text Color", "dynamic": false, "info": "The text color of the name", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "text_color", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" } }, "tool_mode": false }, "type": "ChatOutput" }, "dragging": false, "height": 302, "id": "ChatOutput-jessc", "measured": { "height": 302, "width": 320 }, "position": { "x": 2649.190603849412, "y": 841.0466487848925 }, "positionAbsolute": { "x": 2649.190603849412, "y": 841.0466487848925 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "ChatInput-my2y0", "node": { "base_classes": [ "Message" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Get chat inputs from the Playground.", "display_name": "Chat Input", "documentation": "", "edited": false, "field_order": [ "input_value", "should_store_message", "sender", "sender_name", "session_id", "files", "background_color", "chat_icon", "text_color" ], "frozen": false, "icon": "MessagesSquare", "legacy": false, "metadata": {}, "minimized": true, "output_types": [], "outputs": [ { "allows_loop": false, "cache": true, "display_name": "Chat Message", "group_outputs": false, "method": "message_response", "name": "message", "options": null, "required_inputs": null, "selected": "Message", "tool_mode": true, "types": [ "Message" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "background_color": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Background Color", "dynamic": false, "info": "The background color of the icon.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "background_color", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "chat_icon": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Icon", "dynamic": false, "info": "The icon of the message.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "chat_icon", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from langflow.base.data.utils import IMG_FILE_TYPES, TEXT_FILE_TYPES\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput\nfrom langflow.io import (\n DropdownInput,\n FileInput,\n MessageTextInput,\n MultilineInput,\n Output,\n)\nfrom langflow.schema.message import Message\nfrom langflow.utils.constants import (\n MESSAGE_SENDER_AI,\n MESSAGE_SENDER_NAME_USER,\n MESSAGE_SENDER_USER,\n)\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"MessagesSquare\"\n name = \"ChatInput\"\n minimized = True\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Input Text\",\n value=\"\",\n info=\"Message to be passed as input.\",\n input_types=[],\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_USER,\n info=\"Type of sender.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_USER,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n FileInput(\n name=\"files\",\n display_name=\"Files\",\n file_types=TEXT_FILE_TYPES + IMG_FILE_TYPES,\n info=\"Files to be sent with the message.\",\n advanced=True,\n is_list=True,\n temp_file=True,\n ),\n MessageTextInput(\n name=\"background_color\",\n display_name=\"Background Color\",\n info=\"The background color of the icon.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"chat_icon\",\n display_name=\"Icon\",\n info=\"The icon of the message.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"text_color\",\n display_name=\"Text Color\",\n info=\"The text color of the name\",\n advanced=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Chat Message\", name=\"message\", method=\"message_response\"),\n ]\n\n async def message_response(self) -> Message:\n background_color = self.background_color\n text_color = self.text_color\n icon = self.chat_icon\n\n message = await Message.create(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n files=self.files,\n properties={\n \"background_color\": background_color,\n \"text_color\": text_color,\n \"icon\": icon,\n },\n )\n if self.session_id and isinstance(message, Message) and self.should_store_message:\n stored_message = await self.send_message(\n message,\n )\n self.message.value = stored_message\n message = stored_message\n\n self.status = message\n return message\n" }, "files": { "_input_type": "FileInput", "advanced": true, "display_name": "Files", "dynamic": false, "fileTypes": [ "txt", "md", "mdx", "csv", "json", "yaml", "yml", "xml", "html", "htm", "pdf", "docx", "py", "sh", "sql", "js", "ts", "tsx", "jpg", "jpeg", "png", "bmp", "image" ], "file_path": "", "info": "Files to be sent with the message.", "list": true, "list_add_label": "Add More", "name": "files", "placeholder": "", "required": false, "show": true, "temp_file": true, "title_case": false, "trace_as_metadata": true, "type": "file", "value": "" }, "input_value": { "_input_type": "MultilineInput", "advanced": false, "copy_field": false, "display_name": "Input Text", "dynamic": false, "info": "Message to be passed as input.", "input_types": [], "list": false, "list_add_label": "Add More", "load_from_db": false, "multiline": true, "name": "input_value", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "list users" }, "sender": { "_input_type": "DropdownInput", "advanced": true, "combobox": false, "dialog_inputs": {}, "display_name": "Sender Type", "dynamic": false, "info": "Type of sender.", "name": "sender", "options": [ "Machine", "User" ], "options_metadata": [], "placeholder": "", "required": false, "show": true, "title_case": false, "toggle": false, "tool_mode": false, "trace_as_metadata": true, "type": "str", "value": "User" }, "sender_name": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Sender Name", "dynamic": false, "info": "Name of the sender.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "sender_name", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "User" }, "session_id": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Session ID", "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "session_id", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "should_store_message": { "_input_type": "BoolInput", "advanced": true, "display_name": "Store Messages", "dynamic": false, "info": "Store the message in the history.", "list": false, "list_add_label": "Add More", "name": "should_store_message", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": true }, "text_color": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Text Color", "dynamic": false, "info": "The text color of the name", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "text_color", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" } }, "tool_mode": false }, "type": "ChatInput" }, "dragging": false, "height": 302, "id": "ChatInput-my2y0", "measured": { "height": 302, "width": 320 }, "position": { "x": 557.6262725075026, "y": 724.8518930903978 }, "positionAbsolute": { "x": 557.6262725075026, "y": 724.8518930903978 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "ToolkitComponent-mfg6v", "node": { "base_classes": [ "BaseTool", "Data" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Combines multiple tools into a single list of tools.", "display_name": "Toolkit", "documentation": "", "edited": true, "field_order": [ "tools" ], "frozen": false, "icon": "pocket-knife", "lf_version": "1.0.17", "output_types": [], "outputs": [ { "cache": true, "display_name": "Tools", "method": "generate_toolkit", "name": "generated_tools", "selected": "BaseTool", "types": [ "BaseTool" ], "value": "__UNDEFINED__" }, { "cache": true, "display_name": "Tool Data", "hidden": true, "method": "generate_tool_data", "name": "tool_data", "selected": "Data", "types": [ "Data" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from typing import List\r\nfrom langflow.custom import Component\r\nfrom langflow.inputs import HandleInput, MessageTextInput\r\nfrom langflow.template import Output\r\nfrom langflow.field_typing import Tool, Embeddings\r\nfrom langchain.tools.base import BaseTool, StructuredTool\r\nfrom langflow.schema import Data\r\n\r\nclass ToolkitComponent(Component):\r\n display_name = \"Toolkit\"\r\n description = \"Combines multiple tools into a single list of tools.\"\r\n icon = \"pocket-knife\"\r\n\r\n inputs = [\r\n HandleInput(\r\n name=\"tools\",\r\n display_name=\"Tools\",\r\n input_types=[\"Tool\"],\r\n info=\"List of tools to combine.\",\r\n is_list=True,\r\n ),\r\n ]\r\n\r\n outputs = [\r\n Output(display_name=\"Tools\", name=\"generated_tools\", method=\"generate_toolkit\"),\r\n Output(display_name=\"Tool Data\", name=\"tool_data\", method=\"generate_tool_data\"),\r\n ]\r\n\r\n def generate_toolkit(self) -> List[BaseTool]:\r\n combined_tools = []\r\n name_count = {}\r\n for index, tool in enumerate(self.tools):\r\n self.log(f\"Processing tool {index}: {type(tool)}\")\r\n if isinstance(tool, (BaseTool, StructuredTool)):\r\n processed_tool = tool\r\n elif hasattr(tool, 'build_tool'):\r\n processed_tool = tool.build_tool()\r\n else:\r\n self.log(f\"Unsupported tool type: {type(tool)}. Attempting to process anyway.\")\r\n processed_tool = tool\r\n\r\n original_name = getattr(processed_tool, 'name', f\"UnnamedTool_{index}\")\r\n self.log(f\"Original tool name: {original_name}\")\r\n\r\n if original_name not in name_count:\r\n name_count[original_name] = 0\r\n final_name = original_name\r\n else:\r\n name_count[original_name] += 1\r\n final_name = f\"{original_name}_{name_count[original_name]}\"\r\n\r\n if hasattr(processed_tool, 'name'):\r\n processed_tool.name = final_name\r\n\r\n self.log(f\"Final tool name: {final_name}\")\r\n\r\n if isinstance(processed_tool, StructuredTool) and hasattr(processed_tool, 'args_schema'):\r\n processed_tool.args_schema.name = f\"{final_name}_Schema\"\r\n\r\n combined_tools.append(processed_tool)\r\n\r\n debug_info = \"\\n\".join([f\"Tool {i}: {getattr(tool, 'name', f'UnnamedTool_{i}')} (Original: {getattr(tool, '_original_name', 'N/A')}) - Type: {type(tool)}\" for i, tool in enumerate(combined_tools)])\r\n self.log(\"Final toolkit composition:\")\r\n self.log(debug_info)\r\n\r\n\r\n self.status = combined_tools\r\n return combined_tools\r\n\r\n def generate_tool_data(self) -> List[Data]:\r\n tool_data = []\r\n for tool in self.generate_toolkit():\r\n tool_data.append(Data(\r\n data={\r\n \"name\": getattr(tool, 'name', 'Unnamed Tool'),\r\n \"description\": getattr(tool, 'description', 'No description available')\r\n }\r\n ))\r\n return tool_data" }, "tools": { "_input_type": "HandleInput", "advanced": false, "display_name": "Tools", "dynamic": false, "info": "List of tools to combine.", "input_types": [ "Tool" ], "list": true, "name": "tools", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "other", "value": "" } } }, "type": "ToolkitComponent" }, "dragging": false, "height": 292, "id": "ToolkitComponent-mfg6v", "measured": { "height": 292, "width": 320 }, "position": { "x": 1731.8884789245508, "y": 1378.7846304343796 }, "positionAbsolute": { "x": 1731.8884789245508, "y": 1378.7846304343796 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "OpenAIModel-gIFGV", "node": { "base_classes": [ "LanguageModel", "Message" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Generates text using OpenAI LLMs.", "display_name": "OpenAI", "documentation": "", "edited": false, "field_order": [ "input_value", "system_message", "stream", "max_tokens", "model_kwargs", "json_mode", "model_name", "openai_api_base", "api_key", "temperature", "seed", "max_retries", "timeout" ], "frozen": false, "icon": "OpenAI", "legacy": false, "metadata": { "keywords": [ "model", "llm", "language model", "large language model" ] }, "minimized": false, "output_types": [], "outputs": [ { "allows_loop": false, "cache": true, "display_name": "Model Response", "group_outputs": false, "method": "text_response", "name": "text_output", "options": null, "required_inputs": [], "selected": "Message", "tool_mode": true, "types": [ "Message" ], "value": "__UNDEFINED__" }, { "allows_loop": false, "cache": true, "display_name": "Language Model", "group_outputs": false, "method": "build_model", "name": "model_output", "options": null, "required_inputs": [ "api_key" ], "selected": "LanguageModel", "tool_mode": true, "types": [ "LanguageModel" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "api_key": { "_input_type": "SecretStrInput", "advanced": false, "display_name": "OpenAI API Key", "dynamic": false, "info": "The OpenAI API Key to use for the OpenAI model.", "input_types": [], "load_from_db": true, "name": "api_key", "password": true, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "str", "value": "" }, "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from typing import Any\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import (\n OPENAI_MODEL_NAMES,\n OPENAI_REASONING_MODEL_NAMES,\n)\nfrom langflow.field_typing import LanguageModel\nfrom langflow.field_typing.range_spec import RangeSpec\nfrom langflow.inputs import BoolInput, DictInput, DropdownInput, IntInput, SecretStrInput, SliderInput, StrInput\nfrom langflow.logging import logger\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n name = \"OpenAIModel\"\n\n inputs = [\n *LCModelComponent._base_inputs,\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n range_spec=RangeSpec(min=0, max=128000),\n ),\n DictInput(\n name=\"model_kwargs\",\n display_name=\"Model Kwargs\",\n advanced=True,\n info=\"Additional keyword arguments to pass to the model.\",\n ),\n BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n advanced=True,\n info=\"If True, it will output JSON regardless of passing a schema.\",\n ),\n DropdownInput(\n name=\"model_name\",\n display_name=\"Model Name\",\n advanced=False,\n options=OPENAI_MODEL_NAMES + OPENAI_REASONING_MODEL_NAMES,\n value=OPENAI_MODEL_NAMES[1],\n combobox=True,\n real_time_refresh=True,\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. \"\n \"Defaults to https://api.openai.com/v1. \"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n required=True,\n ),\n SliderInput(\n name=\"temperature\",\n display_name=\"Temperature\",\n value=0.1,\n range_spec=RangeSpec(min=0, max=1, step=0.01),\n show=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\n ),\n IntInput(\n name=\"max_retries\",\n display_name=\"Max Retries\",\n info=\"The maximum number of retries to make when generating.\",\n advanced=True,\n value=5,\n ),\n IntInput(\n name=\"timeout\",\n display_name=\"Timeout\",\n info=\"The timeout for requests to OpenAI completion API.\",\n advanced=True,\n value=700,\n ),\n ]\n\n def build_model(self) -> LanguageModel: # type: ignore[type-var]\n parameters = {\n \"api_key\": SecretStr(self.api_key).get_secret_value() if self.api_key else None,\n \"model_name\": self.model_name,\n \"max_tokens\": self.max_tokens or None,\n \"model_kwargs\": self.model_kwargs or {},\n \"base_url\": self.openai_api_base or \"https://api.openai.com/v1\",\n \"seed\": self.seed,\n \"max_retries\": self.max_retries,\n \"timeout\": self.timeout,\n \"temperature\": self.temperature if self.temperature is not None else 0.1,\n }\n\n logger.info(f\"Model name: {self.model_name}\")\n if self.model_name in OPENAI_REASONING_MODEL_NAMES:\n logger.info(\"Getting reasoning model parameters\")\n parameters.pop(\"temperature\")\n parameters.pop(\"seed\")\n output = ChatOpenAI(**parameters)\n if self.json_mode:\n output = output.bind(response_format={\"type\": \"json_object\"})\n\n return output\n\n def _get_exception_message(self, e: Exception):\n \"\"\"Get a message from an OpenAI exception.\n\n Args:\n e (Exception): The exception to get the message from.\n\n Returns:\n str: The message from the exception.\n \"\"\"\n try:\n from openai import BadRequestError\n except ImportError:\n return None\n if isinstance(e, BadRequestError):\n message = e.body.get(\"message\")\n if message:\n return message\n return None\n\n def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict:\n if field_name in {\"base_url\", \"model_name\", \"api_key\"} and field_value in OPENAI_REASONING_MODEL_NAMES:\n build_config[\"temperature\"][\"show\"] = False\n build_config[\"seed\"][\"show\"] = False\n if field_name in {\"base_url\", \"model_name\", \"api_key\"} and field_value in OPENAI_MODEL_NAMES:\n build_config[\"temperature\"][\"show\"] = True\n build_config[\"seed\"][\"show\"] = True\n return build_config\n" }, "input_value": { "_input_type": "MessageInput", "advanced": false, "display_name": "Input", "dynamic": false, "info": "", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "input_value", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "json_mode": { "_input_type": "BoolInput", "advanced": true, "display_name": "JSON Mode", "dynamic": false, "info": "If True, it will output JSON regardless of passing a schema.", "list": false, "list_add_label": "Add More", "name": "json_mode", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": false }, "max_retries": { "_input_type": "IntInput", "advanced": true, "display_name": "Max Retries", "dynamic": false, "info": "The maximum number of retries to make when generating.", "list": false, "list_add_label": "Add More", "name": "max_retries", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "int", "value": 5 }, "max_tokens": { "_input_type": "IntInput", "advanced": true, "display_name": "Max Tokens", "dynamic": false, "info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.", "list": false, "list_add_label": "Add More", "name": "max_tokens", "placeholder": "", "range_spec": { "max": 128000, "min": 0, "step": 0.1, "step_type": "float" }, "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "int", "value": "" }, "model_kwargs": { "_input_type": "DictInput", "advanced": true, "display_name": "Model Kwargs", "dynamic": false, "info": "Additional keyword arguments to pass to the model.", "list": false, "list_add_label": "Add More", "name": "model_kwargs", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "type": "dict", "value": {} }, "model_name": { "_input_type": "DropdownInput", "advanced": false, "combobox": true, "dialog_inputs": {}, "display_name": "Model Name", "dynamic": false, "info": "", "name": "model_name", "options": [ "gpt-4o-mini", "gpt-4o", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4.5-preview", "gpt-4-turbo", "gpt-4-turbo-preview", "gpt-4", "gpt-3.5-turbo", "o1" ], "options_metadata": [], "placeholder": "", "real_time_refresh": true, "required": false, "show": true, "title_case": false, "toggle": false, "tool_mode": false, "trace_as_metadata": true, "type": "str", "value": "gpt-4.1" }, "openai_api_base": { "_input_type": "StrInput", "advanced": true, "display_name": "OpenAI API Base", "dynamic": false, "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.", "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "openai_api_base", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "str", "value": "" }, "seed": { "_input_type": "IntInput", "advanced": true, "display_name": "Seed", "dynamic": false, "info": "The seed controls the reproducibility of the job.", "list": false, "list_add_label": "Add More", "name": "seed", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "int", "value": 1 }, "stream": { "_input_type": "BoolInput", "advanced": true, "display_name": "Stream", "dynamic": false, "info": "Stream the response from the model. Streaming works only in Chat.", "list": false, "list_add_label": "Add More", "name": "stream", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": false }, "system_message": { "_input_type": "MultilineInput", "advanced": false, "copy_field": false, "display_name": "System Message", "dynamic": false, "info": "System message to pass to the model.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "multiline": true, "name": "system_message", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "temperature": { "_input_type": "SliderInput", "advanced": false, "display_name": "Temperature", "dynamic": false, "info": "", "max_label": "", "max_label_icon": "", "min_label": "", "min_label_icon": "", "name": "temperature", "placeholder": "", "range_spec": { "max": 1, "min": 0, "step": 0.01, "step_type": "float" }, "required": false, "show": true, "slider_buttons": false, "slider_buttons_options": [], "slider_input": false, "title_case": false, "tool_mode": false, "type": "slider", "value": 0.1 }, "timeout": { "_input_type": "IntInput", "advanced": true, "display_name": "Timeout", "dynamic": false, "info": "The timeout for requests to OpenAI completion API.", "list": false, "list_add_label": "Add More", "name": "timeout", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "int", "value": 700 } }, "tool_mode": false }, "type": "OpenAIModel" }, "dragging": false, "height": 433, "id": "OpenAIModel-gIFGV", "measured": { "height": 433, "width": 320 }, "position": { "x": 1718.9773974162958, "y": 603.4642741725065 }, "positionAbsolute": { "x": 1718.9773974162958, "y": 603.4642741725065 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "Memory-4Jm4h", "node": { "base_classes": [ "DataFrame" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Stores or retrieves stored chat messages from Langflow tables or an external memory.", "display_name": "Message History", "documentation": "", "edited": false, "field_order": [ "mode", "message", "memory", "sender", "sender_name", "n_messages", "session_id", "order", "template" ], "frozen": false, "icon": "message-square-more", "legacy": false, "metadata": {}, "minimized": false, "output_types": [], "outputs": [ { "allows_loop": false, "cache": true, "display_name": "Messages", "group_outputs": false, "hidden": null, "method": "retrieve_messages_dataframe", "name": "dataframe", "options": null, "required_inputs": null, "selected": "DataFrame", "tool_mode": true, "types": [ "DataFrame" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from typing import Any, cast\n\nfrom langflow.custom import Component\nfrom langflow.inputs import HandleInput\nfrom langflow.io import DropdownInput, IntInput, MessageTextInput, MultilineInput, Output, TabInput\nfrom langflow.memory import aget_messages, astore_message\nfrom langflow.schema import Data, dotdict\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.message import Message\nfrom langflow.utils.component_utils import set_current_fields, set_field_display\nfrom langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_AI, MESSAGE_SENDER_USER\n\n\nclass MemoryComponent(Component):\n display_name = \"Message History\"\n description = \"Stores or retrieves stored chat messages from Langflow tables or an external memory.\"\n icon = \"message-square-more\"\n name = \"Memory\"\n default_keys = [\"mode\", \"memory\"]\n mode_config = {\n \"Store\": [\"message\", \"memory\", \"sender\", \"sender_name\", \"session_id\"],\n \"Retrieve\": [\"n_messages\", \"order\", \"template\", \"memory\"],\n }\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Retrieve\", \"Store\"],\n value=\"Retrieve\",\n info=\"Operation mode: Store messages or Retrieve messages.\",\n real_time_refresh=True,\n ),\n MessageTextInput(\n name=\"message\",\n display_name=\"Message\",\n info=\"The chat message to be stored.\",\n tool_mode=True,\n dynamic=True,\n show=False,\n ),\n HandleInput(\n name=\"memory\",\n display_name=\"External Memory\",\n input_types=[\"Memory\"],\n info=\"Retrieve messages from an external memory. If empty, it will use the Langflow tables.\",\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER, \"Machine and User\"],\n value=\"Machine and User\",\n info=\"Filter by sender type.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Filter by sender name.\",\n advanced=True,\n show=False,\n ),\n IntInput(\n name=\"n_messages\",\n display_name=\"Number of Messages\",\n value=100,\n info=\"Number of messages to retrieve.\",\n advanced=True,\n show=False,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n DropdownInput(\n name=\"order\",\n display_name=\"Order\",\n options=[\"Ascending\", \"Descending\"],\n value=\"Ascending\",\n info=\"Order of the messages.\",\n advanced=True,\n tool_mode=True,\n required=True,\n show=False,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {sender} or any other key in the message data.\",\n value=\"{sender_name}: {text}\",\n advanced=True,\n show=False,\n ),\n ]\n\n outputs = [Output(display_name=\"Messages\", name=\"dataframe\", method=\"retrieve_messages_dataframe\", dynamic=True)]\n\n def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict:\n \"\"\"Dynamically show only the relevant output based on the selected output type.\"\"\"\n if field_name == \"mode\":\n # Start with empty outputs\n frontend_node[\"outputs\"] = []\n if field_value == \"Store\":\n frontend_node[\"outputs\"] = [\n Output(\n display_name=\"Stored Messages\",\n name=\"stored_messages\",\n method=\"store_message\",\n hidden=True,\n dynamic=True,\n )\n ]\n if field_value == \"Retrieve\":\n frontend_node[\"outputs\"] = [\n Output(\n display_name=\"Messages\", name=\"dataframe\", method=\"retrieve_messages_dataframe\", dynamic=True\n )\n ]\n return frontend_node\n\n async def retrieve_messages(self) -> Data:\n sender = self.sender\n sender_name = self.sender_name\n session_id = self.session_id\n n_messages = self.n_messages\n order = \"DESC\" if self.order == \"Descending\" else \"ASC\"\n\n if sender == \"Machine and User\":\n sender = None\n\n if self.memory and not hasattr(self.memory, \"aget_messages\"):\n memory_name = type(self.memory).__name__\n err_msg = f\"External Memory object ({memory_name}) must have 'aget_messages' method.\"\n raise AttributeError(err_msg)\n # Check if n_messages is None or 0\n if n_messages == 0:\n stored = []\n elif self.memory:\n # override session_id\n self.memory.session_id = session_id\n\n stored = await self.memory.aget_messages()\n # langchain memories are supposed to return messages in ascending order\n if order == \"DESC\":\n stored = stored[::-1]\n if n_messages:\n stored = stored[:n_messages]\n stored = [Message.from_lc_message(m) for m in stored]\n if sender:\n expected_type = MESSAGE_SENDER_AI if sender == MESSAGE_SENDER_AI else MESSAGE_SENDER_USER\n stored = [m for m in stored if m.type == expected_type]\n else:\n stored = await aget_messages(\n sender=sender,\n sender_name=sender_name,\n session_id=session_id,\n limit=n_messages,\n order=order,\n )\n self.status = stored\n return cast(Data, stored)\n\n async def retrieve_messages_dataframe(self) -> DataFrame:\n \"\"\"Convert the retrieved messages into a DataFrame.\n\n Returns:\n DataFrame: A DataFrame containing the message data.\n \"\"\"\n messages = await self.retrieve_messages()\n return DataFrame(messages)\n\n async def store_message(self) -> Message:\n message = Message(text=self.message) if isinstance(self.message, str) else self.message\n\n message.session_id = self.session_id or message.session_id\n message.sender = self.sender or message.sender or MESSAGE_SENDER_AI\n message.sender_name = self.sender_name or message.sender_name or MESSAGE_SENDER_NAME_AI\n\n stored_messages: list[Message] = []\n\n if self.memory:\n self.memory.session_id = message.session_id\n lc_message = message.to_lc_message()\n await self.memory.aadd_messages([lc_message])\n\n stored_messages = await self.memory.aget_messages() or []\n\n stored_messages = [Message.from_lc_message(m) for m in stored_messages] if stored_messages else []\n\n if message.sender:\n stored_messages = [m for m in stored_messages if m.sender == message.sender]\n else:\n await astore_message(message, flow_id=self.graph.flow_id)\n stored_messages = (\n await aget_messages(\n session_id=message.session_id, sender_name=message.sender_name, sender=message.sender\n )\n or []\n )\n\n if not stored_messages:\n msg = \"No messages were stored. Please ensure that the session ID and sender are properly set.\"\n raise ValueError(msg)\n\n stored_message = stored_messages[0]\n self.status = stored_message\n return stored_message\n\n def update_build_config(\n self,\n build_config: dotdict,\n field_value: Any, # noqa: ARG002\n field_name: str | None = None, # noqa: ARG002\n ) -> dotdict:\n return set_current_fields(\n build_config=build_config,\n action_fields=self.mode_config,\n selected_action=build_config[\"mode\"][\"value\"],\n default_fields=self.default_keys,\n func=set_field_display,\n )\n" }, "memory": { "_input_type": "HandleInput", "advanced": true, "display_name": "External Memory", "dynamic": false, "info": "Retrieve messages from an external memory. If empty, it will use the Langflow tables.", "input_types": [ "Memory" ], "list": false, "list_add_label": "Add More", "name": "memory", "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "other", "value": "" }, "message": { "_input_type": "MessageTextInput", "advanced": false, "display_name": "Message", "dynamic": true, "info": "The chat message to be stored.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "message", "placeholder": "", "required": false, "show": false, "title_case": false, "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "mode": { "_input_type": "TabInput", "advanced": false, "display_name": "Mode", "dynamic": false, "info": "Operation mode: Store messages or Retrieve messages.", "name": "mode", "options": [ "Retrieve", "Store" ], "placeholder": "", "real_time_refresh": true, "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "tab", "value": "Retrieve" }, "n_messages": { "_input_type": "IntInput", "advanced": true, "display_name": "Number of Messages", "dynamic": false, "info": "Number of messages to retrieve.", "list": false, "list_add_label": "Add More", "name": "n_messages", "placeholder": "", "required": false, "show": false, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "int", "value": 100 }, "order": { "_input_type": "DropdownInput", "advanced": true, "combobox": false, "dialog_inputs": {}, "display_name": "Order", "dynamic": false, "info": "Order of the messages.", "name": "order", "options": [ "Ascending", "Descending" ], "options_metadata": [], "placeholder": "", "required": true, "show": false, "title_case": false, "toggle": false, "tool_mode": true, "trace_as_metadata": true, "type": "str", "value": "Ascending" }, "sender": { "_input_type": "DropdownInput", "advanced": true, "combobox": false, "dialog_inputs": {}, "display_name": "Sender Type", "dynamic": false, "info": "Filter by sender type.", "name": "sender", "options": [ "Machine", "User", "Machine and User" ], "options_metadata": [], "placeholder": "", "required": false, "show": true, "title_case": false, "toggle": false, "tool_mode": false, "trace_as_metadata": true, "type": "str", "value": "Machine and User" }, "sender_name": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Sender Name", "dynamic": false, "info": "Filter by sender name.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "sender_name", "placeholder": "", "required": false, "show": false, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "session_id": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Session ID", "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "session_id", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" }, "template": { "_input_type": "MultilineInput", "advanced": true, "copy_field": false, "display_name": "Template", "dynamic": false, "info": "The template to use for formatting the data. It can contain the keys {text}, {sender} or any other key in the message data.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "multiline": true, "name": "template", "placeholder": "", "required": false, "show": false, "title_case": false, "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "{sender_name}: {text}" } }, "tool_mode": false }, "type": "Memory" }, "dragging": false, "height": 244, "id": "Memory-4Jm4h", "measured": { "height": 244, "width": 320 }, "position": { "x": 1240.7186213296432, "y": 1059.5754404393747 }, "positionAbsolute": { "x": 1240.7186213296432, "y": 1059.5754404393747 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "Prompt-S7cEu", "node": { "base_classes": [ "Message" ], "beta": false, "conditional_paths": [], "custom_fields": { "template": [ "CURRENT_DATE" ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", "documentation": "", "edited": false, "field_order": [ "template", "tool_placeholder" ], "frozen": false, "icon": "braces", "legacy": false, "metadata": {}, "minimized": false, "output_types": [], "outputs": [ { "allows_loop": false, "cache": true, "display_name": "Prompt", "group_outputs": false, "hidden": null, "method": "build_prompt", "name": "prompt", "options": null, "required_inputs": null, "selected": "Message", "tool_mode": true, "types": [ "Message" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "CURRENT_DATE": { "advanced": false, "display_name": "CURRENT_DATE", "dynamic": false, "field_type": "str", "fileTypes": [], "file_path": "", "info": "", "input_types": [ "Message" ], "list": false, "load_from_db": false, "multiline": true, "name": "CURRENT_DATE", "placeholder": "", "required": false, "show": true, "title_case": false, "type": "str", "value": "" }, "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from langflow.base.prompts.api_utils import process_prompt_template\nfrom langflow.custom import Component\nfrom langflow.inputs.inputs import DefaultPromptField\nfrom langflow.io import MessageTextInput, Output, PromptInput\nfrom langflow.schema.message import Message\nfrom langflow.template.utils import update_template_values\n\n\nclass PromptComponent(Component):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"braces\"\n trace_type = \"prompt\"\n name = \"Prompt\"\n\n inputs = [\n PromptInput(name=\"template\", display_name=\"Template\"),\n MessageTextInput(\n name=\"tool_placeholder\",\n display_name=\"Tool Placeholder\",\n tool_mode=True,\n advanced=True,\n info=\"A placeholder input for tool mode.\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Prompt\", name=\"prompt\", method=\"build_prompt\"),\n ]\n\n async def build_prompt(self) -> Message:\n prompt = Message.from_template(**self._attributes)\n self.status = prompt.text\n return prompt\n\n def _update_template(self, frontend_node: dict):\n prompt_template = frontend_node[\"template\"][\"template\"][\"value\"]\n custom_fields = frontend_node[\"custom_fields\"]\n frontend_node_template = frontend_node[\"template\"]\n _ = process_prompt_template(\n template=prompt_template,\n name=\"template\",\n custom_fields=custom_fields,\n frontend_node_template=frontend_node_template,\n )\n return frontend_node\n\n async def update_frontend_node(self, new_frontend_node: dict, current_frontend_node: dict):\n \"\"\"This function is called after the code validation is done.\"\"\"\n frontend_node = await super().update_frontend_node(new_frontend_node, current_frontend_node)\n template = frontend_node[\"template\"][\"template\"][\"value\"]\n # Kept it duplicated for backwards compatibility\n _ = process_prompt_template(\n template=template,\n name=\"template\",\n custom_fields=frontend_node[\"custom_fields\"],\n frontend_node_template=frontend_node[\"template\"],\n )\n # Now that template is updated, we need to grab any values that were set in the current_frontend_node\n # and update the frontend_node with those values\n update_template_values(new_template=frontend_node, previous_template=current_frontend_node[\"template\"])\n return frontend_node\n\n def _get_fallback_input(self, **kwargs):\n return DefaultPromptField(**kwargs)\n" }, "template": { "_input_type": "PromptInput", "advanced": false, "display_name": "Template", "dynamic": false, "info": "", "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "template", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_input": true, "type": "prompt", "value": "\nYou are a Notion Agent, an AI assistant designed to help users interact with their Notion workspace. Your role is to understand user requests, utilize the appropriate Notion tools to fulfill these requests, and communicate clearly with the user throughout the process.\n\nGeneral Guidelines:\n\n1. Carefully analyze each user request to determine which tool(s) you need to use.\n\n2. Before using any tool, ensure you have all the necessary information. If you need more details, ask the user clear and concise questions.\n\n3. When using a tool, provide a brief explanation to the user about what you're doing and why.\n\n4. After using a tool, interpret the results for the user in a clear, concise manner.\n\n5. If a task requires multiple steps, outline your plan to the user before proceeding.\n\n6. If you encounter an error or limitation, explain it to the user and suggest possible solutions or alternative approaches.\n\n7. Always maintain a helpful and professional tone in your interactions.\n\n8. Be proactive in offering suggestions or alternatives if the user's initial request can't be fulfilled exactly as stated.\n\n9. When providing information or results, focus on relevance and clarity. Summarize when necessary, but provide details when they're important.\n\n10. If a user's request is unclear or could be interpreted in multiple ways, ask for clarification before proceeding.\n\n11. After completing a task, summarize what was accomplished and suggest any relevant next steps or additional actions the user might want to take.\n\n12. If a user asks about capabilities you don't have or tools you can't access, clearly explain your limitations and suggest alternative ways to assist if possible.\n\nRemember, your primary goal is to assist the user effectively with their Notion-related tasks using the provided tools. Always strive for clarity, accuracy, and helpfulness in your interactions. Adapt your communication style to the user's level of technical understanding and familiarity with Notion.\n\nNow, you're ready to assist the user\n\nToday is: {CURRENT_DATE}\n" }, "tool_placeholder": { "_input_type": "MessageTextInput", "advanced": true, "display_name": "Tool Placeholder", "dynamic": false, "info": "A placeholder input for tool mode.", "input_types": [ "Message" ], "list": false, "list_add_label": "Add More", "load_from_db": false, "name": "tool_placeholder", "placeholder": "", "required": false, "show": true, "title_case": false, "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "" } }, "tool_mode": false }, "type": "Prompt" }, "dragging": false, "height": 416, "id": "Prompt-S7cEu", "measured": { "height": 416, "width": 320 }, "position": { "x": 1227.4862876736101, "y": 616.3826667128244 }, "positionAbsolute": { "x": 1227.4862876736101, "y": 616.3826667128244 }, "selected": false, "type": "genericNode", "width": 384 }, { "data": { "id": "CurrentDateComponent-mEpAU", "node": { "base_classes": [ "Message" ], "beta": false, "conditional_paths": [], "custom_fields": {}, "description": "Returns the current date and time in the selected timezone.", "display_name": "Current Date", "documentation": "", "edited": true, "field_order": [ "timezone" ], "frozen": false, "icon": "clock", "lf_version": "1.0.17", "official": false, "output_types": [], "outputs": [ { "cache": true, "display_name": "Current Date", "method": "get_current_date", "name": "current_date", "selected": "Message", "types": [ "Message" ], "value": "__UNDEFINED__" } ], "pinned": false, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from datetime import datetime\r\nfrom zoneinfo import ZoneInfo\r\nfrom typing import List\r\n\r\nfrom langflow.custom import Component\r\nfrom langflow.io import DropdownInput, Output\r\nfrom langflow.schema.message import Message\r\n\r\nclass CurrentDateComponent(Component):\r\n display_name = \"Current Date 🕰️\"\r\n description = \"Returns the current date and time in the selected timezone.\"\r\n icon = \"clock\"\r\n\r\n inputs = [\r\n DropdownInput(\r\n name=\"timezone\",\r\n display_name=\"Timezone\",\r\n options=[\r\n \"UTC\",\r\n \"US/Eastern\",\r\n \"US/Central\",\r\n \"US/Mountain\",\r\n \"US/Pacific\",\r\n \"Europe/London\",\r\n \"Europe/Paris\",\r\n \"Asia/Tokyo\",\r\n \"Australia/Sydney\",\r\n \"America/Sao_Paulo\",\r\n \"America/Cuiaba\",\r\n ],\r\n value=\"UTC\",\r\n info=\"Select the timezone for the current date and time.\",\r\n ),\r\n ]\r\n\r\n outputs = [\r\n Output(display_name=\"Current Date\", name=\"current_date\", method=\"get_current_date\"),\r\n ]\r\n\r\n def get_current_date(self) -> Message:\r\n try:\r\n tz = ZoneInfo(self.timezone)\r\n current_date = datetime.now(tz).strftime(\"%Y-%m-%d %H:%M:%S %Z\")\r\n result = f\"Current date and time in {self.timezone}: {current_date}\"\r\n self.status = result\r\n return Message(text=result)\r\n except Exception as e:\r\n error_message = f\"Error: {str(e)}\"\r\n self.status = error_message\r\n return Message(text=error_message)" }, "timezone": { "_input_type": "DropdownInput", "advanced": false, "combobox": false, "display_name": "Timezone", "dynamic": false, "info": "Select the timezone for the current date and time.", "name": "timezone", "options": [ "UTC", "US/Eastern", "US/Central", "US/Mountain", "US/Pacific", "Europe/London", "Europe/Paris", "Asia/Tokyo", "Australia/Sydney", "America/Sao_Paulo", "America/Cuiaba" ], "placeholder": "", "required": false, "show": true, "title_case": false, "trace_as_metadata": true, "type": "str", "value": "UTC" } } }, "showNode": false, "type": "CurrentDateComponent" }, "dragging": false, "height": 96, "id": "CurrentDateComponent-mEpAU", "measured": { "height": 96, "width": 192 }, "position": { "x": 1092.5108512311297, "y": 868.3249850335523 }, "positionAbsolute": { "x": 1092.5108512311297, "y": 868.3249850335523 }, "selected": false, "type": "genericNode", "width": 96 }, { "data": { "id": "TypeConverterComponent-I2ppC", "node": { "base_classes": [ "Message" ], "beta": false, "category": "processing", "conditional_paths": [], "custom_fields": {}, "description": "Convert between different types (Message, Data, DataFrame)", "display_name": "Type Convert", "documentation": "", "edited": false, "field_order": [ "input_data", "output_type" ], "frozen": false, "icon": "repeat", "key": "TypeConverterComponent", "legacy": false, "metadata": {}, "minimized": false, "output_types": [], "outputs": [ { "allows_loop": false, "cache": true, "display_name": "Message Output", "group_outputs": false, "method": "convert_to_message", "name": "message_output", "selected": "Message", "tool_mode": true, "types": [ "Message" ], "value": "__UNDEFINED__" } ], "pinned": false, "score": 0.007568328950209746, "template": { "_type": "Component", "code": { "advanced": true, "dynamic": true, "fileTypes": [], "file_path": "", "info": "", "list": false, "load_from_db": false, "multiline": true, "name": "code", "password": false, "placeholder": "", "required": true, "show": true, "title_case": false, "type": "code", "value": "from typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import HandleInput, Output, TabInput\nfrom langflow.schema import Data, DataFrame, Message\n\n\ndef convert_to_message(v) -> Message:\n \"\"\"Convert input to Message type.\n\n Args:\n v: Input to convert (Message, Data, DataFrame, or dict)\n\n Returns:\n Message: Converted Message object\n \"\"\"\n return v if isinstance(v, Message) else v.to_message()\n\n\ndef convert_to_data(v: DataFrame | Data | Message | dict) -> Data:\n \"\"\"Convert input to Data type.\n\n Args:\n v: Input to convert (Message, Data, DataFrame, or dict)\n\n Returns:\n Data: Converted Data object\n \"\"\"\n if isinstance(v, dict):\n return Data(v)\n return v if isinstance(v, Data) else v.to_data()\n\n\ndef convert_to_dataframe(v: DataFrame | Data | Message | dict) -> DataFrame:\n \"\"\"Convert input to DataFrame type.\n\n Args:\n v: Input to convert (Message, Data, DataFrame, or dict)\n\n Returns:\n DataFrame: Converted DataFrame object\n \"\"\"\n if isinstance(v, dict):\n return DataFrame([v])\n return v if isinstance(v, DataFrame) else v.to_dataframe()\n\n\nclass TypeConverterComponent(Component):\n display_name = \"Type Convert\"\n description = \"Convert between different types (Message, Data, DataFrame)\"\n icon = \"repeat\"\n\n inputs = [\n HandleInput(\n name=\"input_data\",\n display_name=\"Input\",\n input_types=[\"Message\", \"Data\", \"DataFrame\"],\n info=\"Accept Message, Data or DataFrame as input\",\n required=True,\n ),\n TabInput(\n name=\"output_type\",\n display_name=\"Output Type\",\n options=[\"Message\", \"Data\", \"DataFrame\"],\n info=\"Select the desired output data type\",\n real_time_refresh=True,\n value=\"Message\",\n ),\n ]\n\n outputs = [Output(display_name=\"Message Output\", name=\"message_output\", method=\"convert_to_message\")]\n\n def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict:\n \"\"\"Dynamically show only the relevant output based on the selected output type.\"\"\"\n if field_name == \"output_type\":\n # Start with empty outputs\n frontend_node[\"outputs\"] = []\n\n # Add only the selected output type\n if field_value == \"Message\":\n frontend_node[\"outputs\"].append(\n Output(display_name=\"Message Output\", name=\"message_output\", method=\"convert_to_message\").to_dict()\n )\n elif field_value == \"Data\":\n frontend_node[\"outputs\"].append(\n Output(display_name=\"Data Output\", name=\"data_output\", method=\"convert_to_data\").to_dict()\n )\n elif field_value == \"DataFrame\":\n frontend_node[\"outputs\"].append(\n Output(\n display_name=\"DataFrame Output\", name=\"dataframe_output\", method=\"convert_to_dataframe\"\n ).to_dict()\n )\n\n return frontend_node\n\n def convert_to_message(self) -> Message:\n \"\"\"Convert input to Message type.\"\"\"\n return convert_to_message(self.input_data[0] if isinstance(self.input_data, list) else self.input_data)\n\n def convert_to_data(self) -> Data:\n \"\"\"Convert input to Data type.\"\"\"\n return convert_to_data(self.input_data[0] if isinstance(self.input_data, list) else self.input_data)\n\n def convert_to_dataframe(self) -> DataFrame:\n \"\"\"Convert input to DataFrame type.\"\"\"\n return convert_to_dataframe(self.input_data[0] if isinstance(self.input_data, list) else self.input_data)\n" }, "input_data": { "_input_type": "HandleInput", "advanced": false, "display_name": "Input", "dynamic": false, "info": "Accept Message, Data or DataFrame as input", "input_types": [ "Message", "Data", "DataFrame" ], "list": false, "list_add_label": "Add More", "name": "input_data", "placeholder": "", "required": true, "show": true, "title_case": false, "trace_as_metadata": true, "type": "other", "value": "" }, "output_type": { "_input_type": "TabInput", "advanced": false, "display_name": "Output Type", "dynamic": false, "info": "Select the desired output data type", "name": "output_type", "options": [ "Message", "Data", "DataFrame" ], "placeholder": "", "real_time_refresh": true, "required": false, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "tab", "value": "Message" } }, "tool_mode": false }, "showNode": true, "type": "TypeConverterComponent" }, "id": "TypeConverterComponent-I2ppC", "measured": { "height": 261, "width": 320 }, "position": { "x": 1600.3037160700787, "y": 1139.5045362063886 }, "selected": true, "type": "genericNode" } ], "viewport": { "x": -401.8206379384965, "y": -136.05236574544563, "zoom": 0.5897759459412302 } }, "description": "This flow creates an AI assistant that interacts with your Notion workspace. It understands natural language requests, performs actions in Notion (like creating pages or searching for information), and provides helpful responses. To use it, simply start a conversation by asking the agent to perform a Notion-related task, and it will guide you through the process, making it easy to manage your Notion workspace through chat.", "endpoint_name": null, "id": "c6c53b77-f2f5-46bb-b481-80de2055deef", "is_component": false, "last_tested_version": "1.4.2", "name": "Conversational Notion Agent", "tags": [] }