{ "id": "66747dc4-fc29-491b-833a-5d5d031d680f", "data": { "nodes": [ { "id": "ChatInput-2x8vF", "type": "genericNode", "position": { "x": 250, "y": 453 }, "data": { "node": { "template": { "_type": "Component", "files": { "trace_as_metadata": true, "file_path": "", "fileTypes": [ "txt", "md", "mdx", "csv", "json", "yaml", "yml", "xml", "html", "htm", "pdf", "docx", "py", "sh", "sql", "js", "ts", "tsx", "jpg", "jpeg", "png", "bmp", "image" ], "list": true, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "files", "value": "", "display_name": "Files", "advanced": true, "dynamic": false, "info": "Files to be sent with the message.", "title_case": false, "type": "file", "_input_type": "FileInput" }, "background_color": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "background_color", "value": "", "display_name": "Background Color", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The background color of the icon.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "chat_icon": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "chat_icon", "value": "", "display_name": "Icon", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The icon of the message.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "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=\"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 ),\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=\"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", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false }, "input_value": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "input_value", "value": "", "display_name": "Text", "advanced": false, "input_types": [], "dynamic": false, "info": "Message to be passed as input.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "sender": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Machine", "User" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "sender", "value": "User", "display_name": "Sender Type", "advanced": true, "dynamic": false, "info": "Type of sender.", "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "sender_name": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "sender_name", "value": "User", "display_name": "Sender Name", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Name of the sender.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "session_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "session_id", "value": "", "display_name": "Session ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "should_store_message": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "should_store_message", "value": true, "display_name": "Store Messages", "advanced": true, "dynamic": false, "info": "Store the message in the history.", "title_case": false, "type": "bool", "_input_type": "BoolInput" }, "text_color": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "text_color", "value": "", "display_name": "Text Color", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The text color of the name", "title_case": false, "type": "str", "_input_type": "MessageTextInput" } }, "description": "Get chat inputs from the Playground.", "icon": "MessagesSquare", "base_classes": [ "Message" ], "display_name": "Chat Input", "documentation": "", "minimized": true, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "message", "display_name": "Message", "method": "message_response", "value": "__UNDEFINED__", "cache": true, "allows_loop": false, "tool_mode": true } ], "field_order": [ "input_value", "should_store_message", "sender", "sender_name", "session_id", "files", "background_color", "chat_icon", "text_color" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": false, "type": "ChatInput", "id": "ChatInput-2x8vF" }, "selected": false, "measured": { "width": 192, "height": 66 }, "dragging": false }, { "id": "Prompt-CLQNW", "type": "genericNode", "position": { "x": 417, "y": 114 }, "data": { "node": { "template": { "_type": "Component", "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "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 = \"prompts\"\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 Message\", 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", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false }, "template": { "tool_mode": false, "trace_as_input": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "template", "value": "Generate the learning objectives for the topic that will be given by the user. Imagine that is for K-12 education.", "display_name": "Template", "advanced": false, "dynamic": false, "info": "", "title_case": false, "type": "prompt", "_input_type": "PromptInput" }, "tool_placeholder": { "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tool_placeholder", "value": "", "display_name": "Tool Placeholder", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "A placeholder input for tool mode.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" } }, "description": "Create a prompt template with dynamic variables.", "icon": "prompts", "is_input": null, "is_output": null, "is_composition": null, "base_classes": [ "Message" ], "name": "", "display_name": "Prompt", "documentation": "", "minimized": false, "custom_fields": { "template": [] }, "output_types": [], "full_path": null, "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "prompt", "hidden": null, "display_name": "Prompt Message", "method": "build_prompt", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "template", "tool_placeholder" ], "beta": false, "legacy": false, "error": null, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "Prompt", "id": "Prompt-CLQNW" }, "selected": false, "measured": { "width": 320, "height": 255 }, "dragging": false }, { "id": "Agent-6ilGB", "type": "genericNode", "position": { "x": 856, "y": 104 }, "data": { "node": { "template": { "_type": "Component", "memory": { "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "memory", "value": "", "display_name": "External Memory", "advanced": true, "input_types": [ "Memory" ], "dynamic": false, "info": "Retrieve messages from an external memory. If empty, it will use the Langflow tables.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "tools": { "trace_as_metadata": true, "list": true, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tools", "value": "", "display_name": "Tools", "advanced": false, "input_types": [ "Tool" ], "dynamic": false, "info": "These are the tools that the agent can use to help with tasks.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "add_current_date_tool": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "add_current_date_tool", "value": true, "display_name": "Current Date", "advanced": true, "dynamic": false, "info": "If true, will add a tool to the agent that returns the current date.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "agent_description": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "agent_description", "value": "A helpful assistant with access to the following tools:", "display_name": "Agent Description [Deprecated]", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "agent_llm": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Amazon Bedrock", "Anthropic", "Azure OpenAI", "Google Generative AI", "Groq", "NVIDIA", "OpenAI", "Custom" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "agent_llm", "value": "Google Generative AI", "display_name": "Model Provider", "advanced": false, "input_types": [], "dynamic": false, "info": "The provider of the language model that the agent will use to generate responses.", "real_time_refresh": true, "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n except Exception as e:\n # Log the error for debugging purposes\n logger.error(f\"Error retrieving language model: {e}\")\n raise\n\n try:\n self.chat_history = await self.get_memory_data()\n except Exception as e:\n logger.error(f\"Error retrieving chat history: {e}\")\n raise\n\n if self.add_current_date_tool:\n try:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n # Convert CurrentDateComponent to a StructuredTool\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if isinstance(current_date_tool, StructuredTool):\n self.tools.append(current_date_tool)\n else:\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n except Exception as e:\n logger.error(f\"Error adding current date tool: {e}\")\n raise\n\n if not self.tools:\n msg = \"Tools are required to run the agent.\"\n logger.error(msg)\n raise ValueError(msg)\n\n try:\n self.set(\n llm=llm_model,\n tools=self.tools,\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n except Exception as e:\n logger.error(f\"Error setting up the agent: {e}\")\n raise\n\n return await self.run_agent(agent)\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if isinstance(self.agent_llm, str):\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n return (\n self._build_llm_model(component_class, inputs, prefix),\n display_name,\n )\n except Exception as e:\n msg = f\"Error building {self.agent_llm} language model\"\n raise ValueError(msg) from e\n return self.agent_llm, None\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def to_toolkit(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=self.get_tool_name(), tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false, "input_types": [] }, "handle_parsing_errors": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "handle_parsing_errors", "value": true, "display_name": "Handle Parse Errors", "advanced": true, "dynamic": false, "info": "Should the Agent fix errors when reading user input for better processing?", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "input_value": { "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "input_value", "value": "", "display_name": "Input", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The input provided by the user for the agent to process.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "max_iterations": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_iterations", "value": 15, "display_name": "Max Iterations", "advanced": true, "dynamic": false, "info": "The maximum number of attempts the agent can make to complete its task before it stops.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "n_messages": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n_messages", "value": 100, "display_name": "Number of Messages", "advanced": true, "dynamic": false, "info": "Number of messages to retrieve.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "order": { "tool_mode": true, "trace_as_metadata": true, "options": [ "Ascending", "Descending" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "order", "value": "Ascending", "display_name": "Order", "advanced": true, "dynamic": false, "info": "Order of the messages.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Machine", "User", "Machine and User" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "sender", "value": "Machine and User", "display_name": "Sender Type", "advanced": true, "dynamic": false, "info": "Filter by sender type.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender_name": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "sender_name", "value": "", "display_name": "Sender Name", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Filter by sender name.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "session_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "session_id", "value": "", "display_name": "Session ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "system_prompt": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "system_prompt", "value": "You are a helpful assistant that can use tools to answer questions and perform tasks.", "display_name": "Agent Instructions", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "System Prompt: Initial instructions and context provided to guide the agent's behavior.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "template": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "template", "value": "{sender_name}: {text}", "display_name": "Template", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "verbose": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "verbose", "value": true, "display_name": "Verbose", "advanced": true, "dynamic": false, "info": "", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "max_output_tokens": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_output_tokens", "value": "", "display_name": "Max Output Tokens", "advanced": false, "dynamic": false, "info": "The maximum number of tokens to generate.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "model_name": { "tool_mode": false, "trace_as_metadata": true, "options": [ "learnlm-1.5-pro-experimental", "gemini-pro-vision", "gemini-pro", "gemini-exp-1206", "gemini-2.0-pro-exp-02-05", "gemini-2.0-pro-exp", "gemini-2.0-flash-thinking-exp-1219", "gemini-2.0-flash-thinking-exp-01-21", "gemini-2.0-flash-thinking-exp", "gemini-2.0-flash-lite-preview-02-05", "gemini-2.0-flash-lite-preview", "gemini-2.0-flash-exp", "gemini-2.0-flash-001", "gemini-2.0-flash", "gemini-1.5-pro-latest", "gemini-1.5-pro-002", "gemini-1.5-pro-001", "gemini-1.5-pro", "gemini-1.5-flash-latest", "gemini-1.5-flash-8b-latest", "gemini-1.5-flash-8b-exp-0924", "gemini-1.5-flash-8b-exp-0827", "gemini-1.5-flash-8b-001", "gemini-1.5-flash-8b", "gemini-1.5-flash-002", "gemini-1.5-flash-001-tuning", "gemini-1.5-flash-001", "gemini-1.5-flash", "gemini-1.0-pro-vision-latest", "gemini-1.0-pro-latest", "gemini-1.0-pro-001", "gemini-1.0-pro" ], "options_metadata": [], "combobox": true, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "model_name", "value": "gemini-2.0-flash", "display_name": "Model", "advanced": false, "dynamic": false, "info": "To see the model names, first choose a provider. Then, enter your API key and click the refresh button next to the model name.", "real_time_refresh": false, "refresh_button": true, "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "api_key": { "load_from_db": false, "required": true, "placeholder": "", "show": true, "name": "api_key", "value": "", "display_name": "Google API Key", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The Google API Key to use for the Google Generative AI.", "real_time_refresh": true, "title_case": false, "password": true, "type": "str", "_input_type": "SecretStrInput" }, "top_p": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_p", "value": "", "display_name": "Top P", "advanced": true, "dynamic": false, "info": "The maximum cumulative probability of tokens to consider when sampling.", "title_case": false, "type": "float", "_input_type": "FloatInput", "input_types": [] }, "temperature": { "tool_mode": false, "min_label": "", "max_label": "", "min_label_icon": "", "max_label_icon": "", "slider_buttons": false, "slider_buttons_options": [], "slider_input": false, "range_spec": { "step_type": "float", "min": 0, "max": 2, "step": 0.01 }, "required": false, "placeholder": "", "show": true, "name": "temperature", "value": 0.1, "display_name": "Temperature", "advanced": true, "dynamic": false, "info": "Controls randomness. Lower values are more deterministic, higher values are more creative.", "title_case": false, "type": "slider", "_input_type": "SliderInput", "input_types": [] }, "n": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n", "value": "", "display_name": "N", "advanced": true, "dynamic": false, "info": "Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "top_k": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_k", "value": "", "display_name": "Top K", "advanced": true, "dynamic": false, "info": "Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "tool_model_enabled": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tool_model_enabled", "value": false, "display_name": "Tool Model Enabled", "advanced": true, "dynamic": false, "info": "Whether to use the tool model.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] } }, "description": "Define the agent's instructions, then enter a task to complete using tools.", "icon": "bot", "base_classes": [ "Message" ], "display_name": "Objectives Agent", "documentation": "", "minimized": false, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "response", "hidden": null, "display_name": "Response", "method": "message_response", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "agent_llm", "max_tokens", "model_kwargs", "json_mode", "model_name", "openai_api_base", "api_key", "temperature", "seed", "system_prompt", "tools", "input_value", "handle_parsing_errors", "verbose", "max_iterations", "agent_description", "memory", "sender", "sender_name", "n_messages", "session_id", "order", "template", "add_current_date_tool" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "Agent", "id": "Agent-6ilGB" }, "selected": false, "measured": { "width": 320, "height": 703 }, "dragging": false }, { "id": "Agent-e7sUF", "type": "genericNode", "position": { "x": 1365, "y": 105 }, "data": { "node": { "template": { "_type": "Component", "memory": { "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "memory", "value": "", "display_name": "External Memory", "advanced": true, "input_types": [ "Memory" ], "dynamic": false, "info": "Retrieve messages from an external memory. If empty, it will use the Langflow tables.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "tools": { "trace_as_metadata": true, "list": true, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tools", "value": "", "display_name": "Tools", "advanced": false, "input_types": [ "Tool" ], "dynamic": false, "info": "These are the tools that the agent can use to help with tasks.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "add_current_date_tool": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "add_current_date_tool", "value": true, "display_name": "Current Date", "advanced": true, "dynamic": false, "info": "If true, will add a tool to the agent that returns the current date.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "agent_description": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "agent_description", "value": "A helpful assistant with access to the following tools:", "display_name": "Agent Description [Deprecated]", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "agent_llm": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Amazon Bedrock", "Anthropic", "Azure OpenAI", "Google Generative AI", "Groq", "NVIDIA", "OpenAI", "Custom" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "agent_llm", "value": "Google Generative AI", "display_name": "Model Provider", "advanced": false, "input_types": [], "dynamic": false, "info": "The provider of the language model that the agent will use to generate responses.", "real_time_refresh": true, "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n except Exception as e:\n # Log the error for debugging purposes\n logger.error(f\"Error retrieving language model: {e}\")\n raise\n\n try:\n self.chat_history = await self.get_memory_data()\n except Exception as e:\n logger.error(f\"Error retrieving chat history: {e}\")\n raise\n\n if self.add_current_date_tool:\n try:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n # Convert CurrentDateComponent to a StructuredTool\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if isinstance(current_date_tool, StructuredTool):\n self.tools.append(current_date_tool)\n else:\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n except Exception as e:\n logger.error(f\"Error adding current date tool: {e}\")\n raise\n\n if not self.tools:\n msg = \"Tools are required to run the agent.\"\n logger.error(msg)\n raise ValueError(msg)\n\n try:\n self.set(\n llm=llm_model,\n tools=self.tools,\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n except Exception as e:\n logger.error(f\"Error setting up the agent: {e}\")\n raise\n\n return await self.run_agent(agent)\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if isinstance(self.agent_llm, str):\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n return (\n self._build_llm_model(component_class, inputs, prefix),\n display_name,\n )\n except Exception as e:\n msg = f\"Error building {self.agent_llm} language model\"\n raise ValueError(msg) from e\n return self.agent_llm, None\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def to_toolkit(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=self.get_tool_name(), tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false, "input_types": [] }, "handle_parsing_errors": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "handle_parsing_errors", "value": true, "display_name": "Handle Parse Errors", "advanced": true, "dynamic": false, "info": "Should the Agent fix errors when reading user input for better processing?", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "input_value": { "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "input_value", "value": "", "display_name": "Input", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The input provided by the user for the agent to process.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "max_iterations": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_iterations", "value": 15, "display_name": "Max Iterations", "advanced": true, "dynamic": false, "info": "The maximum number of attempts the agent can make to complete its task before it stops.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "n_messages": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n_messages", "value": 100, "display_name": "Number of Messages", "advanced": true, "dynamic": false, "info": "Number of messages to retrieve.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "order": { "tool_mode": true, "trace_as_metadata": true, "options": [ "Ascending", "Descending" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "order", "value": "Ascending", "display_name": "Order", "advanced": true, "dynamic": false, "info": "Order of the messages.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Machine", "User", "Machine and User" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "sender", "value": "Machine and User", "display_name": "Sender Type", "advanced": true, "dynamic": false, "info": "Filter by sender type.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender_name": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "sender_name", "value": "", "display_name": "Sender Name", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Filter by sender name.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "session_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "session_id", "value": "", "display_name": "Session ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "system_prompt": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "system_prompt", "value": "Based on the learning objectives created by the previous agent, generate a basic lesson plan. If it is too extensive, divide it into several days. For lenght considerations, think about 1 hour class per day.", "display_name": "Agent Instructions", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "System Prompt: Initial instructions and context provided to guide the agent's behavior.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "template": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "template", "value": "{sender_name}: {text}", "display_name": "Template", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "verbose": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "verbose", "value": true, "display_name": "Verbose", "advanced": true, "dynamic": false, "info": "", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "max_output_tokens": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_output_tokens", "value": "", "display_name": "Max Output Tokens", "advanced": false, "dynamic": false, "info": "The maximum number of tokens to generate.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "model_name": { "tool_mode": false, "trace_as_metadata": true, "options": [ "learnlm-1.5-pro-experimental", "gemini-pro-vision", "gemini-pro", "gemini-exp-1206", "gemini-2.0-pro-exp-02-05", "gemini-2.0-pro-exp", "gemini-2.0-flash-thinking-exp-1219", "gemini-2.0-flash-thinking-exp-01-21", "gemini-2.0-flash-thinking-exp", "gemini-2.0-flash-lite-preview-02-05", "gemini-2.0-flash-lite-preview", "gemini-2.0-flash-exp", "gemini-2.0-flash-001", "gemini-2.0-flash", "gemini-1.5-pro-latest", "gemini-1.5-pro-002", "gemini-1.5-pro-001", "gemini-1.5-pro", "gemini-1.5-flash-latest", "gemini-1.5-flash-8b-latest", "gemini-1.5-flash-8b-exp-0924", "gemini-1.5-flash-8b-exp-0827", "gemini-1.5-flash-8b-001", "gemini-1.5-flash-8b", "gemini-1.5-flash-002", "gemini-1.5-flash-001-tuning", "gemini-1.5-flash-001", "gemini-1.5-flash", "gemini-1.0-pro-vision-latest", "gemini-1.0-pro-latest", "gemini-1.0-pro-001", "gemini-1.0-pro" ], "options_metadata": [], "combobox": true, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "model_name", "value": "gemini-2.0-flash", "display_name": "Model", "advanced": false, "dynamic": false, "info": "To see the model names, first choose a provider. Then, enter your API key and click the refresh button next to the model name.", "real_time_refresh": false, "refresh_button": true, "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "api_key": { "load_from_db": false, "required": true, "placeholder": "", "show": true, "name": "api_key", "value": "", "display_name": "Google API Key", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The Google API Key to use for the Google Generative AI.", "real_time_refresh": true, "title_case": false, "password": true, "type": "str", "_input_type": "SecretStrInput" }, "top_p": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_p", "value": "", "display_name": "Top P", "advanced": true, "dynamic": false, "info": "The maximum cumulative probability of tokens to consider when sampling.", "title_case": false, "type": "float", "_input_type": "FloatInput", "input_types": [] }, "temperature": { "tool_mode": false, "min_label": "", "max_label": "", "min_label_icon": "", "max_label_icon": "", "slider_buttons": false, "slider_buttons_options": [], "slider_input": false, "range_spec": { "step_type": "float", "min": 0, "max": 2, "step": 0.01 }, "required": false, "placeholder": "", "show": true, "name": "temperature", "value": 0.1, "display_name": "Temperature", "advanced": true, "dynamic": false, "info": "Controls randomness. Lower values are more deterministic, higher values are more creative.", "title_case": false, "type": "slider", "_input_type": "SliderInput", "input_types": [] }, "n": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n", "value": "", "display_name": "N", "advanced": true, "dynamic": false, "info": "Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "top_k": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_k", "value": "", "display_name": "Top K", "advanced": true, "dynamic": false, "info": "Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "tool_model_enabled": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tool_model_enabled", "value": false, "display_name": "Tool Model Enabled", "advanced": true, "dynamic": false, "info": "Whether to use the tool model.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] } }, "description": "Define the agent's instructions, then enter a task to complete using tools.", "icon": "bot", "base_classes": [ "Message" ], "display_name": "Plan Agent", "documentation": "", "minimized": false, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "response", "hidden": null, "display_name": "Response", "method": "message_response", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "agent_llm", "max_tokens", "model_kwargs", "json_mode", "model_name", "openai_api_base", "api_key", "temperature", "seed", "system_prompt", "tools", "input_value", "handle_parsing_errors", "verbose", "max_iterations", "agent_description", "memory", "sender", "sender_name", "n_messages", "session_id", "order", "template", "add_current_date_tool" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "Agent", "id": "Agent-e7sUF" }, "selected": false, "measured": { "width": 320, "height": 703 } }, { "id": "Agent-womuY", "type": "genericNode", "position": { "x": 1867.4884290294667, "y": 21.107154581322682 }, "data": { "node": { "template": { "_type": "Component", "memory": { "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "memory", "value": "", "display_name": "External Memory", "advanced": true, "input_types": [ "Memory" ], "dynamic": false, "info": "Retrieve messages from an external memory. If empty, it will use the Langflow tables.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "tools": { "trace_as_metadata": true, "list": true, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tools", "value": "", "display_name": "Tools", "advanced": false, "input_types": [ "Tool" ], "dynamic": false, "info": "These are the tools that the agent can use to help with tasks.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "add_current_date_tool": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "add_current_date_tool", "value": true, "display_name": "Current Date", "advanced": true, "dynamic": false, "info": "If true, will add a tool to the agent that returns the current date.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "agent_description": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "agent_description", "value": "A helpful assistant with access to the following tools:", "display_name": "Agent Description [Deprecated]", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "agent_llm": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Amazon Bedrock", "Anthropic", "Azure OpenAI", "Google Generative AI", "Groq", "NVIDIA", "OpenAI", "Custom" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "agent_llm", "value": "Google Generative AI", "display_name": "Model Provider", "advanced": false, "input_types": [], "dynamic": false, "info": "The provider of the language model that the agent will use to generate responses.", "real_time_refresh": true, "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n except Exception as e:\n # Log the error for debugging purposes\n logger.error(f\"Error retrieving language model: {e}\")\n raise\n\n try:\n self.chat_history = await self.get_memory_data()\n except Exception as e:\n logger.error(f\"Error retrieving chat history: {e}\")\n raise\n\n if self.add_current_date_tool:\n try:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n # Convert CurrentDateComponent to a StructuredTool\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if isinstance(current_date_tool, StructuredTool):\n self.tools.append(current_date_tool)\n else:\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n except Exception as e:\n logger.error(f\"Error adding current date tool: {e}\")\n raise\n\n if not self.tools:\n msg = \"Tools are required to run the agent.\"\n logger.error(msg)\n raise ValueError(msg)\n\n try:\n self.set(\n llm=llm_model,\n tools=self.tools,\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n except Exception as e:\n logger.error(f\"Error setting up the agent: {e}\")\n raise\n\n return await self.run_agent(agent)\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if isinstance(self.agent_llm, str):\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n return (\n self._build_llm_model(component_class, inputs, prefix),\n display_name,\n )\n except Exception as e:\n msg = f\"Error building {self.agent_llm} language model\"\n raise ValueError(msg) from e\n return self.agent_llm, None\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def to_toolkit(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=self.get_tool_name(), tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false, "input_types": [] }, "handle_parsing_errors": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "handle_parsing_errors", "value": true, "display_name": "Handle Parse Errors", "advanced": true, "dynamic": false, "info": "Should the Agent fix errors when reading user input for better processing?", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "input_value": { "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "input_value", "value": "", "display_name": "Input", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The input provided by the user for the agent to process.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "max_iterations": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_iterations", "value": 15, "display_name": "Max Iterations", "advanced": true, "dynamic": false, "info": "The maximum number of attempts the agent can make to complete its task before it stops.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "n_messages": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n_messages", "value": 100, "display_name": "Number of Messages", "advanced": true, "dynamic": false, "info": "Number of messages to retrieve.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "order": { "tool_mode": true, "trace_as_metadata": true, "options": [ "Ascending", "Descending" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "order", "value": "Ascending", "display_name": "Order", "advanced": true, "dynamic": false, "info": "Order of the messages.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Machine", "User", "Machine and User" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "sender", "value": "Machine and User", "display_name": "Sender Type", "advanced": true, "dynamic": false, "info": "Filter by sender type.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender_name": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "sender_name", "value": "", "display_name": "Sender Name", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Filter by sender name.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "session_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "session_id", "value": "", "display_name": "Session ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "system_prompt": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "system_prompt", "value": "Complement the lesson plan with a list of videos (obtained from YouTube) that students should watch before the class. As response give the updated lesson plan. Make sure that the videos are age appropriate.", "display_name": "Agent Instructions", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "System Prompt: Initial instructions and context provided to guide the agent's behavior.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "template": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "template", "value": "{sender_name}: {text}", "display_name": "Template", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "verbose": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "verbose", "value": true, "display_name": "Verbose", "advanced": true, "dynamic": false, "info": "", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "max_output_tokens": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_output_tokens", "value": "", "display_name": "Max Output Tokens", "advanced": false, "dynamic": false, "info": "The maximum number of tokens to generate.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "model_name": { "tool_mode": false, "trace_as_metadata": true, "options": [ "learnlm-1.5-pro-experimental", "gemini-pro-vision", "gemini-pro", "gemini-exp-1206", "gemini-2.0-pro-exp-02-05", "gemini-2.0-pro-exp", "gemini-2.0-flash-thinking-exp-1219", "gemini-2.0-flash-thinking-exp-01-21", "gemini-2.0-flash-thinking-exp", "gemini-2.0-flash-lite-preview-02-05", "gemini-2.0-flash-lite-preview", "gemini-2.0-flash-exp", "gemini-2.0-flash-001", "gemini-2.0-flash", "gemini-1.5-pro-latest", "gemini-1.5-pro-002", "gemini-1.5-pro-001", "gemini-1.5-pro", "gemini-1.5-flash-latest", "gemini-1.5-flash-8b-latest", "gemini-1.5-flash-8b-exp-0924", "gemini-1.5-flash-8b-exp-0827", "gemini-1.5-flash-8b-001", "gemini-1.5-flash-8b", "gemini-1.5-flash-002", "gemini-1.5-flash-001-tuning", "gemini-1.5-flash-001", "gemini-1.5-flash", "gemini-1.0-pro-vision-latest", "gemini-1.0-pro-latest", "gemini-1.0-pro-001", "gemini-1.0-pro" ], "options_metadata": [], "combobox": true, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "model_name", "value": "gemini-2.0-flash", "display_name": "Model", "advanced": false, "dynamic": false, "info": "To see the model names, first choose a provider. Then, enter your API key and click the refresh button next to the model name.", "real_time_refresh": false, "refresh_button": true, "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "api_key": { "load_from_db": false, "required": true, "placeholder": "", "show": true, "name": "api_key", "value": "", "display_name": "Google API Key", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The Google API Key to use for the Google Generative AI.", "real_time_refresh": true, "title_case": false, "password": true, "type": "str", "_input_type": "SecretStrInput" }, "top_p": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_p", "value": "", "display_name": "Top P", "advanced": true, "dynamic": false, "info": "The maximum cumulative probability of tokens to consider when sampling.", "title_case": false, "type": "float", "_input_type": "FloatInput", "input_types": [] }, "temperature": { "tool_mode": false, "min_label": "", "max_label": "", "min_label_icon": "", "max_label_icon": "", "slider_buttons": false, "slider_buttons_options": [], "slider_input": false, "range_spec": { "step_type": "float", "min": 0, "max": 2, "step": 0.01 }, "required": false, "placeholder": "", "show": true, "name": "temperature", "value": 0.1, "display_name": "Temperature", "advanced": true, "dynamic": false, "info": "Controls randomness. Lower values are more deterministic, higher values are more creative.", "title_case": false, "type": "slider", "_input_type": "SliderInput", "input_types": [] }, "n": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n", "value": "", "display_name": "N", "advanced": true, "dynamic": false, "info": "Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "top_k": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_k", "value": "", "display_name": "Top K", "advanced": true, "dynamic": false, "info": "Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "tool_model_enabled": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tool_model_enabled", "value": false, "display_name": "Tool Model Enabled", "advanced": true, "dynamic": false, "info": "Whether to use the tool model.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] } }, "description": "Define the agent's instructions, then enter a task to complete using tools.", "icon": "bot", "base_classes": [ "Message" ], "display_name": "Video Agent", "documentation": "", "minimized": false, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "response", "hidden": null, "display_name": "Response", "method": "message_response", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "agent_llm", "max_tokens", "model_kwargs", "json_mode", "model_name", "openai_api_base", "api_key", "temperature", "seed", "system_prompt", "tools", "input_value", "handle_parsing_errors", "verbose", "max_iterations", "agent_description", "memory", "sender", "sender_name", "n_messages", "session_id", "order", "template", "add_current_date_tool" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "Agent", "id": "Agent-womuY" }, "selected": false, "measured": { "width": 320, "height": 703 }, "dragging": false }, { "id": "ComposioAPI-RfpkY", "type": "genericNode", "position": { "x": 1433.0873769261334, "y": -425.0395643971953 }, "data": { "node": { "template": { "_type": "Component", "auth_link": { "required": false, "placeholder": "Click to authenticate", "show": false, "name": "auth_link", "value": "", "display_name": "Authentication Link", "advanced": true, "dynamic": true, "info": "Click to authenticate with OAuth2", "title_case": false, "type": "link", "_input_type": "LinkInput", "load_from_db": false }, "action_names": { "tool_mode": false, "trace_as_metadata": true, "options": [ "YOUTUBE_LIST_USER_PLAYLISTS", "YOUTUBE_VIDEO_DETAILS", "YOUTUBE_UPDATE_THUMBNAIL", "YOUTUBE_SEARCH_YOU_TUBE", "YOUTUBE_LIST_CAPTION_TRACK", "YOUTUBE_SUBSCRIBE_CHANNEL", "YOUTUBE_LIST_USER_SUBSCRIPTIONS", "YOUTUBE_LIST_CHANNEL_VIDEOS", "YOUTUBE_UPDATE_VIDEO", "YOUTUBE_LOAD_CAPTIONS" ], "combobox": false, "list": true, "list_add_label": "Add More", "required": true, "placeholder": "", "show": true, "name": "action_names", "value": [ "YOUTUBE_SEARCH_YOU_TUBE" ], "display_name": "Actions to use", "advanced": false, "dynamic": true, "info": "The actions to pass to agent to execute", "title_case": false, "type": "str", "_input_type": "MultiselectInput" }, "api_key": { "load_from_db": false, "required": true, "placeholder": "", "show": true, "name": "api_key", "value": "", "display_name": "Composio API Key", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "Refer to https://docs.composio.dev/faq/api_key/api_key", "real_time_refresh": true, "title_case": false, "password": true, "type": "str", "_input_type": "SecretStrInput" }, "app_credentials": { "load_from_db": false, "required": false, "placeholder": "", "show": false, "name": "app_credentials", "value": "", "display_name": "App Credentials", "advanced": true, "input_types": [ "Message" ], "dynamic": true, "info": "Credentials for app authentication (API Key, Password, etc)", "title_case": false, "password": true, "type": "str", "_input_type": "SecretStrInput" }, "app_names": { "tool_mode": false, "trace_as_metadata": true, "options": [ "ACCELO", "AIRTABLE", "AMAZON", "APALEO", "ASANA", "ATLASSIAN", "ATTIO", "AUTH0", "BATTLENET", "BITBUCKET", "BLACKBAUD", "BLACKBOARD", "BOLDSIGN", "BORNEO", "BOX", "BRAINTREE", "BREX", "BREX_STAGING", "BRIGHTPEARL", "CALENDLY", "CANVA", "CANVAS", "CHATWORK", "CLICKUP", "CONFLUENCE", "CONTENTFUL", "D2LBRIGHTSPACE", "DEEL", "DISCORD", "DISCORDBOT", "DOCUSIGN", "DROPBOX", "DROPBOX_SIGN", "DYNAMICS365", "EPIC_GAMES", "EVENTBRITE", "EXIST", "FACEBOOK", "FIGMA", "FITBIT", "FRESHBOOKS", "FRONT", "GITHUB", "GMAIL", "GMAIL_BETA", "GO_TO_WEBINAR", "GOOGLE_ANALYTICS", "GOOGLE_DRIVE_BETA", "GOOGLE_MAPS", "GOOGLECALENDAR", "GOOGLEDOCS", "GOOGLEDRIVE", "GOOGLEMEET", "GOOGLEPHOTOS", "GOOGLESHEETS", "GOOGLETASKS", "GORGIAS", "GUMROAD", "HARVEST", "HIGHLEVEL", "HUBSPOT", "ICIMS_TALENT_CLOUD", "INTERCOM", "JIRA", "KEAP", "KLAVIYO", "LASTPASS", "LEVER", "LEVER_SANDBOX", "LINEAR", "LINKEDIN", "LINKHUT", "MAILCHIMP", "MICROSOFT_TEAMS", "MICROSOFT_TENANT", "MIRO", "MONDAY", "MURAL", "NETSUITE", "NOTION", "ONE_DRIVE", "OUTLOOK", "PAGERDUTY", "PIPEDRIVE", "PRODUCTBOARD", "REDDIT", "RING_CENTRAL", "RIPPLING", "SAGE", "SALESFORCE", "SEISMIC", "SERVICEM8", "SHARE_POINT", "SHOPIFY", "SLACK", "SLACKBOT", "SMARTRECRUITERS", "SPOTIFY", "SQUARE", "STACK_EXCHANGE", "SURVEY_MONKEY", "TIMELY", "TODOIST", "TONEDEN", "TRELLO", "TWITCH", "TWITTER", "TWITTER_MEDIA", "WAKATIME", "WAVE_ACCOUNTING", "WEBEX", "WIZ", "WRIKE", "XERO", "YANDEX", "YNAB", "YOUTUBE", "ZENDESK", "ZOHO", "ZOHO_BIGIN", "ZOHO_BOOKS", "ZOHO_DESK", "ZOHO_INVENTORY", "ZOHO_INVOICE", "ZOHO_MAIL", "ZOOM" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": true, "placeholder": "", "show": true, "name": "app_names", "value": "YOUTUBE", "display_name": "App Name", "advanced": false, "dynamic": false, "info": "The app name to use. Please refresh after selecting app name", "refresh_button": true, "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "auth_status": { "tool_mode": false, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "auth_status", "value": "✅", "display_name": "Auth Status", "advanced": false, "dynamic": true, "info": "Current authentication status", "title_case": false, "type": "str", "_input_type": "StrInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "# Standard library imports\nfrom collections.abc import Sequence\nfrom typing import Any\n\nimport requests\n\n# Third-party imports\nfrom composio.client.collections import AppAuthScheme\nfrom composio.client.exceptions import NoItemsFound\nfrom composio_langchain import Action, ComposioToolSet\nfrom langchain_core.tools import Tool\nfrom loguru import logger\n\n# Local imports\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import DropdownInput, LinkInput, MessageTextInput, MultiselectInput, SecretStrInput, StrInput\nfrom langflow.io import Output\n\n\nclass ComposioAPIComponent(LCToolComponent):\n display_name: str = \"Composio Tools\"\n description: str = \"Use Composio toolset to run actions with your agent\"\n name = \"ComposioAPI\"\n icon = \"Composio\"\n documentation: str = \"https://docs.composio.dev\"\n\n inputs = [\n # Basic configuration inputs\n MessageTextInput(name=\"entity_id\", display_name=\"Entity ID\", value=\"default\", advanced=True),\n SecretStrInput(\n name=\"api_key\",\n display_name=\"Composio API Key\",\n required=True,\n info=\"Refer to https://docs.composio.dev/faq/api_key/api_key\",\n real_time_refresh=True,\n ),\n DropdownInput(\n name=\"app_names\",\n display_name=\"App Name\",\n options=[],\n value=\"\",\n info=\"The app name to use. Please refresh after selecting app name\",\n refresh_button=True,\n required=True,\n ),\n # Authentication-related inputs (initially hidden)\n SecretStrInput(\n name=\"app_credentials\",\n display_name=\"App Credentials\",\n required=False,\n dynamic=True,\n show=False,\n info=\"Credentials for app authentication (API Key, Password, etc)\",\n load_from_db=False,\n ),\n MessageTextInput(\n name=\"username\",\n display_name=\"Username\",\n required=False,\n dynamic=True,\n show=False,\n info=\"Username for Basic authentication\",\n ),\n LinkInput(\n name=\"auth_link\",\n display_name=\"Authentication Link\",\n value=\"\",\n info=\"Click to authenticate with OAuth2\",\n dynamic=True,\n show=False,\n placeholder=\"Click to authenticate\",\n ),\n StrInput(\n name=\"auth_status\",\n display_name=\"Auth Status\",\n value=\"Not Connected\",\n info=\"Current authentication status\",\n dynamic=True,\n show=False,\n ),\n MultiselectInput(\n name=\"action_names\",\n display_name=\"Actions to use\",\n required=True,\n options=[],\n value=[],\n info=\"The actions to pass to agent to execute\",\n dynamic=True,\n show=False,\n ),\n ]\n\n outputs = [\n Output(name=\"tools\", display_name=\"Tools\", method=\"build_tool\"),\n ]\n\n def _check_for_authorization(self, app: str) -> str:\n \"\"\"Checks if the app is authorized.\n\n Args:\n app (str): The app name to check authorization for.\n\n Returns:\n str: The authorization status or URL.\n \"\"\"\n toolset = self._build_wrapper()\n entity = toolset.client.get_entity(id=self.entity_id)\n try:\n # Check if user is already connected\n entity.get_connection(app=app)\n except NoItemsFound:\n # Get auth scheme for the app\n auth_scheme = self._get_auth_scheme(app)\n return self._handle_auth_by_scheme(entity, app, auth_scheme)\n except Exception: # noqa: BLE001\n logger.exception(\"Authorization error\")\n return \"Error checking authorization\"\n else:\n return f\"{app} CONNECTED\"\n\n def _get_auth_scheme(self, app_name: str) -> AppAuthScheme:\n \"\"\"Get the primary auth scheme for an app.\n\n Args:\n app_name (str): The name of the app to get auth scheme for.\n\n Returns:\n AppAuthScheme: The auth scheme details.\n \"\"\"\n toolset = self._build_wrapper()\n try:\n return toolset.get_auth_scheme_for_app(app=app_name.lower())\n except Exception: # noqa: BLE001\n logger.exception(f\"Error getting auth scheme for {app_name}\")\n return None\n\n def _get_oauth_apps(self, api_key: str) -> list[str]:\n \"\"\"Fetch OAuth-enabled apps from Composio API.\n\n Args:\n api_key (str): The Composio API key.\n\n Returns:\n list[str]: A list containing OAuth-enabled app names.\n \"\"\"\n oauth_apps = []\n try:\n url = \"https://backend.composio.dev/api/v1/apps\"\n headers = {\"x-api-key\": api_key}\n params = {\n \"includeLocal\": \"true\",\n \"additionalFields\": \"auth_schemes\",\n \"sortBy\": \"alphabet\",\n }\n\n response = requests.get(url, headers=headers, params=params, timeout=20)\n data = response.json()\n\n for item in data.get(\"items\", []):\n for auth_scheme in item.get(\"auth_schemes\", []):\n if auth_scheme.get(\"mode\") in [\"OAUTH1\", \"OAUTH2\"]:\n oauth_apps.append(item[\"key\"].upper())\n break\n except requests.RequestException as e:\n logger.error(f\"Error fetching OAuth apps: {e}\")\n return []\n else:\n return oauth_apps\n\n def _handle_auth_by_scheme(self, entity: Any, app: str, auth_scheme: AppAuthScheme) -> str:\n \"\"\"Handle authentication based on the auth scheme.\n\n Args:\n entity (Any): The entity instance.\n app (str): The app name.\n auth_scheme (AppAuthScheme): The auth scheme details.\n\n Returns:\n str: The authentication status or URL.\n \"\"\"\n auth_mode = auth_scheme.auth_mode\n\n try:\n # First check if already connected\n entity.get_connection(app=app)\n except NoItemsFound:\n # If not connected, handle new connection based on auth mode\n if auth_mode == \"API_KEY\":\n if hasattr(self, \"app_credentials\") and self.app_credentials:\n try:\n entity.initiate_connection(\n app_name=app,\n auth_mode=\"API_KEY\",\n auth_config={\"api_key\": self.app_credentials},\n use_composio_auth=False,\n force_new_integration=True,\n )\n except Exception as e: # noqa: BLE001\n logger.error(f\"Error connecting with API Key: {e}\")\n return \"Invalid API Key\"\n else:\n return f\"{app} CONNECTED\"\n return \"Enter API Key\"\n\n if (\n auth_mode == \"BASIC\"\n and hasattr(self, \"username\")\n and hasattr(self, \"app_credentials\")\n and self.username\n and self.app_credentials\n ):\n try:\n entity.initiate_connection(\n app_name=app,\n auth_mode=\"BASIC\",\n auth_config={\"username\": self.username, \"password\": self.app_credentials},\n use_composio_auth=False,\n force_new_integration=True,\n )\n except Exception as e: # noqa: BLE001\n logger.error(f\"Error connecting with Basic Auth: {e}\")\n return \"Invalid credentials\"\n else:\n return f\"{app} CONNECTED\"\n elif auth_mode == \"BASIC\":\n return \"Enter Username and Password\"\n\n if auth_mode == \"OAUTH2\":\n try:\n return self._initiate_default_connection(entity, app)\n except Exception as e: # noqa: BLE001\n logger.error(f\"Error initiating OAuth2: {e}\")\n return \"OAuth2 initialization failed\"\n\n return \"Unsupported auth mode\"\n except Exception as e: # noqa: BLE001\n logger.error(f\"Error checking connection status: {e}\")\n return f\"Error: {e!s}\"\n else:\n return f\"{app} CONNECTED\"\n\n def _initiate_default_connection(self, entity: Any, app: str) -> str:\n connection = entity.initiate_connection(app_name=app, use_composio_auth=True, force_new_integration=True)\n return connection.redirectUrl\n\n def _get_connected_app_names_for_entity(self) -> list[str]:\n toolset = self._build_wrapper()\n connections = toolset.client.get_entity(id=self.entity_id).get_connections()\n return list({connection.appUniqueId for connection in connections})\n\n def _get_normalized_app_name(self) -> str:\n \"\"\"Get app name without connection status suffix.\n\n Returns:\n str: Normalized app name.\n \"\"\"\n return self.app_names.replace(\" ✅\", \"\").replace(\"_connected\", \"\")\n\n def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict: # noqa: ARG002\n # Update the available apps options from the API\n if hasattr(self, \"api_key\") and self.api_key != \"\":\n toolset = self._build_wrapper()\n build_config[\"app_names\"][\"options\"] = self._get_oauth_apps(api_key=self.api_key)\n\n # First, ensure all dynamic fields are hidden by default\n dynamic_fields = [\"app_credentials\", \"username\", \"auth_link\", \"auth_status\", \"action_names\"]\n for field in dynamic_fields:\n if field in build_config:\n if build_config[field][\"value\"] is None or build_config[field][\"value\"] == \"\":\n build_config[field][\"show\"] = False\n build_config[field][\"advanced\"] = True\n build_config[field][\"load_from_db\"] = False\n else:\n build_config[field][\"show\"] = True\n build_config[field][\"advanced\"] = False\n\n if field_name == \"app_names\" and (not hasattr(self, \"app_names\") or not self.app_names):\n build_config[\"auth_status\"][\"show\"] = True\n build_config[\"auth_status\"][\"value\"] = \"Please select an app first\"\n return build_config\n\n if field_name == \"app_names\" and hasattr(self, \"api_key\") and self.api_key != \"\":\n # app_name = self._get_normalized_app_name()\n app_name = self.app_names\n try:\n toolset = self._build_wrapper()\n entity = toolset.client.get_entity(id=self.entity_id)\n\n # Always show auth_status when app is selected\n build_config[\"auth_status\"][\"show\"] = True\n build_config[\"auth_status\"][\"advanced\"] = False\n\n try:\n # Check if already connected\n entity.get_connection(app=app_name)\n build_config[\"auth_status\"][\"value\"] = \"✅\"\n build_config[\"auth_link\"][\"show\"] = False\n # Show action selection for connected apps\n build_config[\"action_names\"][\"show\"] = True\n build_config[\"action_names\"][\"advanced\"] = False\n\n except NoItemsFound:\n # Get auth scheme and show relevant fields\n auth_scheme = self._get_auth_scheme(app_name)\n auth_mode = auth_scheme.auth_mode\n logger.info(f\"Auth mode for {app_name}: {auth_mode}\")\n\n if auth_mode == \"API_KEY\":\n build_config[\"app_credentials\"][\"show\"] = True\n build_config[\"app_credentials\"][\"advanced\"] = False\n build_config[\"app_credentials\"][\"display_name\"] = \"API Key\"\n build_config[\"auth_status\"][\"value\"] = \"Enter API Key\"\n\n elif auth_mode == \"BASIC\":\n build_config[\"username\"][\"show\"] = True\n build_config[\"username\"][\"advanced\"] = False\n build_config[\"app_credentials\"][\"show\"] = True\n build_config[\"app_credentials\"][\"advanced\"] = False\n build_config[\"app_credentials\"][\"display_name\"] = \"Password\"\n build_config[\"auth_status\"][\"value\"] = \"Enter Username and Password\"\n\n elif auth_mode == \"OAUTH2\":\n build_config[\"auth_link\"][\"show\"] = True\n build_config[\"auth_link\"][\"advanced\"] = False\n auth_url = self._initiate_default_connection(entity, app_name)\n build_config[\"auth_link\"][\"value\"] = auth_url\n build_config[\"auth_status\"][\"value\"] = \"Click link to authenticate\"\n\n else:\n build_config[\"auth_status\"][\"value\"] = \"Unsupported auth mode\"\n\n # Update action names if connected\n if build_config[\"auth_status\"][\"value\"] == \"✅\":\n all_action_names = [str(action).replace(\"Action.\", \"\") for action in Action.all()]\n app_action_names = [\n action_name\n for action_name in all_action_names\n if action_name.lower().startswith(app_name.lower() + \"_\")\n ]\n if build_config[\"action_names\"][\"options\"] != app_action_names:\n build_config[\"action_names\"][\"options\"] = app_action_names\n build_config[\"action_names\"][\"value\"] = [app_action_names[0]] if app_action_names else [\"\"]\n\n except Exception as e: # noqa: BLE001\n logger.error(f\"Error checking auth status: {e}, app: {app_name}\")\n build_config[\"auth_status\"][\"value\"] = f\"Error: {e!s}\"\n\n return build_config\n\n def build_tool(self) -> Sequence[Tool]:\n \"\"\"Build Composio tools based on selected actions.\n\n Returns:\n Sequence[Tool]: List of configured Composio tools.\n \"\"\"\n composio_toolset = self._build_wrapper()\n return composio_toolset.get_tools(actions=self.action_names)\n\n def _build_wrapper(self) -> ComposioToolSet:\n \"\"\"Build the Composio toolset wrapper.\n\n Returns:\n ComposioToolSet: The initialized toolset.\n\n Raises:\n ValueError: If the API key is not found or invalid.\n \"\"\"\n try:\n if not self.api_key:\n msg = \"Composio API Key is required\"\n raise ValueError(msg)\n return ComposioToolSet(api_key=self.api_key)\n except ValueError as e:\n logger.error(f\"Error building Composio wrapper: {e}\")\n msg = \"Please provide a valid Composio API Key in the component settings\"\n raise ValueError(msg) from e\n", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false }, "entity_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "entity_id", "value": "default", "display_name": "Entity ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "username": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": false, "name": "username", "value": "", "display_name": "Username", "advanced": true, "input_types": [ "Message" ], "dynamic": true, "info": "Username for Basic authentication", "title_case": false, "type": "str", "_input_type": "MessageTextInput" } }, "description": "Use Composio toolset to run actions with your agent", "icon": "Composio", "base_classes": [ "Tool" ], "display_name": "Composio Tools", "documentation": "https://docs.composio.dev", "minimized": false, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Tool" ], "selected": "Tool", "name": "tools", "hidden": null, "display_name": "Tools", "method": "build_tool", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "entity_id", "api_key", "app_names", "app_credentials", "username", "auth_link", "auth_status", "action_names" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "ComposioAPI", "id": "ComposioAPI-RfpkY" }, "selected": false, "measured": { "width": 320, "height": 495 }, "dragging": false }, { "id": "Agent-g9eV8", "type": "genericNode", "position": { "x": 2445, "y": 30 }, "data": { "node": { "template": { "_type": "Component", "memory": { "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "memory", "value": "", "display_name": "External Memory", "advanced": true, "input_types": [ "Memory" ], "dynamic": false, "info": "Retrieve messages from an external memory. If empty, it will use the Langflow tables.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "tools": { "trace_as_metadata": true, "list": true, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tools", "value": "", "display_name": "Tools", "advanced": false, "input_types": [ "Tool" ], "dynamic": false, "info": "These are the tools that the agent can use to help with tasks.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "add_current_date_tool": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "add_current_date_tool", "value": true, "display_name": "Current Date", "advanced": true, "dynamic": false, "info": "If true, will add a tool to the agent that returns the current date.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "agent_description": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "agent_description", "value": "A helpful assistant with access to the following tools:", "display_name": "Agent Description [Deprecated]", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "agent_llm": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Amazon Bedrock", "Anthropic", "Azure OpenAI", "Google Generative AI", "Groq", "NVIDIA", "OpenAI", "Custom" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "agent_llm", "value": "Google Generative AI", "display_name": "Model Provider", "advanced": false, "input_types": [], "dynamic": false, "info": "The provider of the language model that the agent will use to generate responses.", "real_time_refresh": true, "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n except Exception as e:\n # Log the error for debugging purposes\n logger.error(f\"Error retrieving language model: {e}\")\n raise\n\n try:\n self.chat_history = await self.get_memory_data()\n except Exception as e:\n logger.error(f\"Error retrieving chat history: {e}\")\n raise\n\n if self.add_current_date_tool:\n try:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n # Convert CurrentDateComponent to a StructuredTool\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if isinstance(current_date_tool, StructuredTool):\n self.tools.append(current_date_tool)\n else:\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n except Exception as e:\n logger.error(f\"Error adding current date tool: {e}\")\n raise\n\n if not self.tools:\n msg = \"Tools are required to run the agent.\"\n logger.error(msg)\n raise ValueError(msg)\n\n try:\n self.set(\n llm=llm_model,\n tools=self.tools,\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n except Exception as e:\n logger.error(f\"Error setting up the agent: {e}\")\n raise\n\n return await self.run_agent(agent)\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if isinstance(self.agent_llm, str):\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n return (\n self._build_llm_model(component_class, inputs, prefix),\n display_name,\n )\n except Exception as e:\n msg = f\"Error building {self.agent_llm} language model\"\n raise ValueError(msg) from e\n return self.agent_llm, None\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def to_toolkit(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=self.get_tool_name(), tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false, "input_types": [] }, "handle_parsing_errors": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "handle_parsing_errors", "value": true, "display_name": "Handle Parse Errors", "advanced": true, "dynamic": false, "info": "Should the Agent fix errors when reading user input for better processing?", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "input_value": { "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "input_value", "value": "", "display_name": "Input", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The input provided by the user for the agent to process.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "max_iterations": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_iterations", "value": 15, "display_name": "Max Iterations", "advanced": true, "dynamic": false, "info": "The maximum number of attempts the agent can make to complete its task before it stops.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "n_messages": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n_messages", "value": 100, "display_name": "Number of Messages", "advanced": true, "dynamic": false, "info": "Number of messages to retrieve.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "order": { "tool_mode": true, "trace_as_metadata": true, "options": [ "Ascending", "Descending" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "order", "value": "Ascending", "display_name": "Order", "advanced": true, "dynamic": false, "info": "Order of the messages.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Machine", "User", "Machine and User" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "sender", "value": "Machine and User", "display_name": "Sender Type", "advanced": true, "dynamic": false, "info": "Filter by sender type.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender_name": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "sender_name", "value": "", "display_name": "Sender Name", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Filter by sender name.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "session_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "session_id", "value": "", "display_name": "Session ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "system_prompt": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "system_prompt", "value": "Please evaluate the lesson plan and check if it meets the Common Core standards. As output give original plan plus the recommendations to make it complies with Common Core.", "display_name": "Agent Instructions", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "System Prompt: Initial instructions and context provided to guide the agent's behavior.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "template": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "template", "value": "{sender_name}: {text}", "display_name": "Template", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "verbose": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "verbose", "value": true, "display_name": "Verbose", "advanced": true, "dynamic": false, "info": "", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "max_output_tokens": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_output_tokens", "value": "", "display_name": "Max Output Tokens", "advanced": false, "dynamic": false, "info": "The maximum number of tokens to generate.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "model_name": { "tool_mode": false, "trace_as_metadata": true, "options": [ "learnlm-1.5-pro-experimental", "gemini-pro-vision", "gemini-pro", "gemini-exp-1206", "gemini-2.0-pro-exp-02-05", "gemini-2.0-pro-exp", "gemini-2.0-flash-thinking-exp-1219", "gemini-2.0-flash-thinking-exp-01-21", "gemini-2.0-flash-thinking-exp", "gemini-2.0-flash-lite-preview-02-05", "gemini-2.0-flash-lite-preview", "gemini-2.0-flash-exp", "gemini-2.0-flash-001", "gemini-2.0-flash", "gemini-1.5-pro-latest", "gemini-1.5-pro-002", "gemini-1.5-pro-001", "gemini-1.5-pro", "gemini-1.5-flash-latest", "gemini-1.5-flash-8b-latest", "gemini-1.5-flash-8b-exp-0924", "gemini-1.5-flash-8b-exp-0827", "gemini-1.5-flash-8b-001", "gemini-1.5-flash-8b", "gemini-1.5-flash-002", "gemini-1.5-flash-001-tuning", "gemini-1.5-flash-001", "gemini-1.5-flash", "gemini-1.0-pro-vision-latest", "gemini-1.0-pro-latest", "gemini-1.0-pro-001", "gemini-1.0-pro" ], "options_metadata": [], "combobox": true, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "model_name", "value": "learnlm-1.5-pro-experimental", "display_name": "Model", "advanced": false, "dynamic": false, "info": "To see the model names, first choose a provider. Then, enter your API key and click the refresh button next to the model name.", "real_time_refresh": false, "refresh_button": true, "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "api_key": { "load_from_db": false, "required": true, "placeholder": "", "show": true, "name": "api_key", "value": "", "display_name": "Google API Key", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The Google API Key to use for the Google Generative AI.", "real_time_refresh": true, "title_case": false, "password": true, "type": "str", "_input_type": "SecretStrInput" }, "top_p": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_p", "value": "", "display_name": "Top P", "advanced": true, "dynamic": false, "info": "The maximum cumulative probability of tokens to consider when sampling.", "title_case": false, "type": "float", "_input_type": "FloatInput", "input_types": [] }, "temperature": { "tool_mode": false, "min_label": "", "max_label": "", "min_label_icon": "", "max_label_icon": "", "slider_buttons": false, "slider_buttons_options": [], "slider_input": false, "range_spec": { "step_type": "float", "min": 0, "max": 2, "step": 0.01 }, "required": false, "placeholder": "", "show": true, "name": "temperature", "value": 0.1, "display_name": "Temperature", "advanced": true, "dynamic": false, "info": "Controls randomness. Lower values are more deterministic, higher values are more creative.", "title_case": false, "type": "slider", "_input_type": "SliderInput", "input_types": [] }, "n": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n", "value": "", "display_name": "N", "advanced": true, "dynamic": false, "info": "Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "top_k": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_k", "value": "", "display_name": "Top K", "advanced": true, "dynamic": false, "info": "Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "tool_model_enabled": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tool_model_enabled", "value": false, "display_name": "Tool Model Enabled", "advanced": true, "dynamic": false, "info": "Whether to use the tool model.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] } }, "description": "Define the agent's instructions, then enter a task to complete using tools.", "icon": "bot", "base_classes": [ "Message" ], "display_name": "Evaluation Agent", "documentation": "", "minimized": false, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "response", "hidden": null, "display_name": "Response", "method": "message_response", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "agent_llm", "max_tokens", "model_kwargs", "json_mode", "model_name", "openai_api_base", "api_key", "temperature", "seed", "system_prompt", "tools", "input_value", "handle_parsing_errors", "verbose", "max_iterations", "agent_description", "memory", "sender", "sender_name", "n_messages", "session_id", "order", "template", "add_current_date_tool" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "Agent", "id": "Agent-g9eV8" }, "selected": false, "measured": { "width": 320, "height": 703 } }, { "id": "ChatOutput-IIhYR", "type": "genericNode", "position": { "x": 3986.305321446119, "y": 102.20276783452312 }, "data": { "node": { "template": { "_type": "Component", "background_color": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "background_color", "value": "", "display_name": "Background Color", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The background color of the icon.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "chat_icon": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "chat_icon", "value": "", "display_name": "Icon", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The icon of the message.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput\nfrom langflow.io import DropdownInput, MessageInput, MessageTextInput, Output\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 MessageInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\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 ]\n outputs = [\n Output(\n display_name=\"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 source_dict[\"source\"] = source\n return Source(**source_dict)\n\n async def message_response(self) -> Message:\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 message = self.input_value if isinstance(self.input_value, Message) else Message(text=self.input_value)\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 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", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false }, "data_template": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "data_template", "value": "{text}", "display_name": "Data Template", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "input_value": { "trace_as_input": true, "tool_mode": false, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "input_value", "value": "", "display_name": "Text", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "Message to be passed as output.", "title_case": false, "type": "str", "_input_type": "MessageInput" }, "sender": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Machine", "User" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "sender", "value": "Machine", "display_name": "Sender Type", "advanced": true, "dynamic": false, "info": "Type of sender.", "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "sender_name": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "sender_name", "value": "AI", "display_name": "Sender Name", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Name of the sender.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "session_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "session_id", "value": "", "display_name": "Session ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "should_store_message": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "should_store_message", "value": true, "display_name": "Store Messages", "advanced": true, "dynamic": false, "info": "Store the message in the history.", "title_case": false, "type": "bool", "_input_type": "BoolInput" }, "text_color": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "text_color", "value": "", "display_name": "Text Color", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The text color of the name", "title_case": false, "type": "str", "_input_type": "MessageTextInput" } }, "description": "Display a chat message in the Playground.", "icon": "MessagesSquare", "base_classes": [ "Message" ], "display_name": "Chat Output", "documentation": "", "minimized": true, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "message", "display_name": "Message", "method": "message_response", "value": "__UNDEFINED__", "cache": true, "allows_loop": false, "tool_mode": true } ], "field_order": [ "input_value", "should_store_message", "sender", "sender_name", "session_id", "data_template", "background_color", "chat_icon", "text_color" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": false, "type": "ChatOutput", "id": "ChatOutput-IIhYR" }, "selected": false, "measured": { "width": 192, "height": 66 }, "dragging": false }, { "id": "Prompt-Od4Ay", "type": "genericNode", "position": { "x": 2951.58883903118, "y": 215.00737440103808 }, "data": { "node": { "template": { "_type": "Component", "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "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 = \"prompts\"\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 Message\", 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", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false }, "template": { "tool_mode": false, "trace_as_input": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "template", "value": "Original Plan:\n{original}\n\nRecommendations:\n{recommendations}", "display_name": "Template", "advanced": false, "dynamic": false, "info": "", "title_case": false, "type": "prompt", "_input_type": "PromptInput" }, "tool_placeholder": { "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tool_placeholder", "value": "", "display_name": "Tool Placeholder", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "A placeholder input for tool mode.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "original": { "field_type": "str", "required": false, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "", "fileTypes": [], "file_path": "", "name": "original", "display_name": "original", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "", "load_from_db": false, "title_case": false, "type": "str" }, "recommendations": { "field_type": "str", "required": false, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "", "fileTypes": [], "file_path": "", "name": "recommendations", "display_name": "recommendations", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "", "load_from_db": false, "title_case": false, "type": "str" } }, "description": "Create a prompt template with dynamic variables.", "icon": "prompts", "is_input": null, "is_output": null, "is_composition": null, "base_classes": [ "Message" ], "name": "", "display_name": "Prompt", "documentation": "", "minimized": false, "custom_fields": { "template": [ "original", "recommendations" ] }, "output_types": [], "full_path": null, "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "prompt", "hidden": null, "display_name": "Prompt Message", "method": "build_prompt", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "template", "tool_placeholder" ], "beta": false, "legacy": false, "error": null, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "Prompt", "id": "Prompt-Od4Ay" }, "selected": false, "measured": { "width": 320, "height": 419 } }, { "id": "Agent-CjuzA", "type": "genericNode", "position": { "x": 3491.1889286619075, "y": 106.2214267618471 }, "data": { "node": { "template": { "_type": "Component", "memory": { "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "memory", "value": "", "display_name": "External Memory", "advanced": true, "input_types": [ "Memory" ], "dynamic": false, "info": "Retrieve messages from an external memory. If empty, it will use the Langflow tables.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "tools": { "trace_as_metadata": true, "list": true, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tools", "value": "", "display_name": "Tools", "advanced": false, "input_types": [ "Tool" ], "dynamic": false, "info": "These are the tools that the agent can use to help with tasks.", "title_case": false, "type": "other", "_input_type": "HandleInput" }, "add_current_date_tool": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "add_current_date_tool", "value": true, "display_name": "Current Date", "advanced": true, "dynamic": false, "info": "If true, will add a tool to the agent that returns the current date.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "agent_description": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "agent_description", "value": "A helpful assistant with access to the following tools:", "display_name": "Agent Description [Deprecated]", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "agent_llm": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Amazon Bedrock", "Anthropic", "Azure OpenAI", "Google Generative AI", "Groq", "NVIDIA", "OpenAI", "Custom" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "agent_llm", "value": "Google Generative AI", "display_name": "Model Provider", "advanced": false, "input_types": [], "dynamic": false, "info": "The provider of the language model that the agent will use to generate responses.", "real_time_refresh": true, "title_case": false, "type": "str", "_input_type": "DropdownInput" }, "code": { "type": "code", "required": true, "placeholder": "", "list": false, "show": true, "multiline": true, "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n except Exception as e:\n # Log the error for debugging purposes\n logger.error(f\"Error retrieving language model: {e}\")\n raise\n\n try:\n self.chat_history = await self.get_memory_data()\n except Exception as e:\n logger.error(f\"Error retrieving chat history: {e}\")\n raise\n\n if self.add_current_date_tool:\n try:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n # Convert CurrentDateComponent to a StructuredTool\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if isinstance(current_date_tool, StructuredTool):\n self.tools.append(current_date_tool)\n else:\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n except Exception as e:\n logger.error(f\"Error adding current date tool: {e}\")\n raise\n\n if not self.tools:\n msg = \"Tools are required to run the agent.\"\n logger.error(msg)\n raise ValueError(msg)\n\n try:\n self.set(\n llm=llm_model,\n tools=self.tools,\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n except Exception as e:\n logger.error(f\"Error setting up the agent: {e}\")\n raise\n\n return await self.run_agent(agent)\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if isinstance(self.agent_llm, str):\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n return (\n self._build_llm_model(component_class, inputs, prefix),\n display_name,\n )\n except Exception as e:\n msg = f\"Error building {self.agent_llm} language model\"\n raise ValueError(msg) from e\n return self.agent_llm, None\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def to_toolkit(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=self.get_tool_name(), tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n", "fileTypes": [], "file_path": "", "password": false, "name": "code", "advanced": true, "dynamic": true, "info": "", "load_from_db": false, "title_case": false, "input_types": [] }, "handle_parsing_errors": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "handle_parsing_errors", "value": true, "display_name": "Handle Parse Errors", "advanced": true, "dynamic": false, "info": "Should the Agent fix errors when reading user input for better processing?", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "input_value": { "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "input_value", "value": "", "display_name": "Input", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The input provided by the user for the agent to process.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "max_iterations": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_iterations", "value": 15, "display_name": "Max Iterations", "advanced": true, "dynamic": false, "info": "The maximum number of attempts the agent can make to complete its task before it stops.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "n_messages": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n_messages", "value": 100, "display_name": "Number of Messages", "advanced": true, "dynamic": false, "info": "Number of messages to retrieve.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "order": { "tool_mode": true, "trace_as_metadata": true, "options": [ "Ascending", "Descending" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "order", "value": "Ascending", "display_name": "Order", "advanced": true, "dynamic": false, "info": "Order of the messages.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender": { "tool_mode": false, "trace_as_metadata": true, "options": [ "Machine", "User", "Machine and User" ], "options_metadata": [], "combobox": false, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "sender", "value": "Machine and User", "display_name": "Sender Type", "advanced": true, "dynamic": false, "info": "Filter by sender type.", "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "sender_name": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "sender_name", "value": "", "display_name": "Sender Name", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "Filter by sender name.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "session_id": { "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "session_id", "value": "", "display_name": "Session ID", "advanced": true, "input_types": [ "Message" ], "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", "title_case": false, "type": "str", "_input_type": "MessageTextInput" }, "system_prompt": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "system_prompt", "value": "Use the recommendations to improve upon the original plan. Make sure to include constructivist activities.", "display_name": "Agent Instructions", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "System Prompt: Initial instructions and context provided to guide the agent's behavior.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "template": { "tool_mode": false, "trace_as_input": true, "multiline": true, "trace_as_metadata": true, "load_from_db": false, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "template", "value": "{sender_name}: {text}", "display_name": "Template", "advanced": true, "input_types": [ "Message" ], "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.", "title_case": false, "type": "str", "_input_type": "MultilineInput" }, "verbose": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "verbose", "value": true, "display_name": "Verbose", "advanced": true, "dynamic": false, "info": "", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] }, "max_output_tokens": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "max_output_tokens", "value": "", "display_name": "Max Output Tokens", "advanced": false, "dynamic": false, "info": "The maximum number of tokens to generate.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "model_name": { "tool_mode": false, "trace_as_metadata": true, "options": [ "learnlm-1.5-pro-experimental", "gemini-pro-vision", "gemini-pro", "gemini-exp-1206", "gemini-2.0-pro-exp-02-05", "gemini-2.0-pro-exp", "gemini-2.0-flash-thinking-exp-1219", "gemini-2.0-flash-thinking-exp-01-21", "gemini-2.0-flash-thinking-exp", "gemini-2.0-flash-lite-preview-02-05", "gemini-2.0-flash-lite-preview", "gemini-2.0-flash-exp", "gemini-2.0-flash-001", "gemini-2.0-flash", "gemini-1.5-pro-latest", "gemini-1.5-pro-002", "gemini-1.5-pro-001", "gemini-1.5-pro", "gemini-1.5-flash-latest", "gemini-1.5-flash-8b-latest", "gemini-1.5-flash-8b-exp-0924", "gemini-1.5-flash-8b-exp-0827", "gemini-1.5-flash-8b-001", "gemini-1.5-flash-8b", "gemini-1.5-flash-002", "gemini-1.5-flash-001-tuning", "gemini-1.5-flash-001", "gemini-1.5-flash", "gemini-1.0-pro-vision-latest", "gemini-1.0-pro-latest", "gemini-1.0-pro-001", "gemini-1.0-pro" ], "options_metadata": [], "combobox": true, "dialog_inputs": {}, "required": false, "placeholder": "", "show": true, "name": "model_name", "value": "gemini-2.0-flash", "display_name": "Model", "advanced": false, "dynamic": false, "info": "To see the model names, first choose a provider. Then, enter your API key and click the refresh button next to the model name.", "real_time_refresh": false, "refresh_button": true, "title_case": false, "type": "str", "_input_type": "DropdownInput", "input_types": [] }, "api_key": { "load_from_db": false, "required": true, "placeholder": "", "show": true, "name": "api_key", "value": "", "display_name": "Google API Key", "advanced": false, "input_types": [ "Message" ], "dynamic": false, "info": "The Google API Key to use for the Google Generative AI.", "real_time_refresh": true, "title_case": false, "password": true, "type": "str", "_input_type": "SecretStrInput" }, "top_p": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_p", "value": "", "display_name": "Top P", "advanced": true, "dynamic": false, "info": "The maximum cumulative probability of tokens to consider when sampling.", "title_case": false, "type": "float", "_input_type": "FloatInput", "input_types": [] }, "temperature": { "tool_mode": false, "min_label": "", "max_label": "", "min_label_icon": "", "max_label_icon": "", "slider_buttons": false, "slider_buttons_options": [], "slider_input": false, "range_spec": { "step_type": "float", "min": 0, "max": 2, "step": 0.01 }, "required": false, "placeholder": "", "show": true, "name": "temperature", "value": 0.1, "display_name": "Temperature", "advanced": true, "dynamic": false, "info": "Controls randomness. Lower values are more deterministic, higher values are more creative.", "title_case": false, "type": "slider", "_input_type": "SliderInput", "input_types": [] }, "n": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "n", "value": "", "display_name": "N", "advanced": true, "dynamic": false, "info": "Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "top_k": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "top_k", "value": "", "display_name": "Top K", "advanced": true, "dynamic": false, "info": "Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", "title_case": false, "type": "int", "_input_type": "IntInput", "input_types": [] }, "tool_model_enabled": { "tool_mode": false, "trace_as_metadata": true, "list": false, "list_add_label": "Add More", "required": false, "placeholder": "", "show": true, "name": "tool_model_enabled", "value": false, "display_name": "Tool Model Enabled", "advanced": true, "dynamic": false, "info": "Whether to use the tool model.", "title_case": false, "type": "bool", "_input_type": "BoolInput", "input_types": [] } }, "description": "Define the agent's instructions, then enter a task to complete using tools.", "icon": "bot", "base_classes": [ "Message" ], "display_name": "Review Agent", "documentation": "", "minimized": false, "custom_fields": {}, "output_types": [], "pinned": false, "conditional_paths": [], "frozen": false, "outputs": [ { "types": [ "Message" ], "selected": "Message", "name": "response", "hidden": null, "display_name": "Response", "method": "message_response", "value": "__UNDEFINED__", "cache": true, "required_inputs": null, "allows_loop": false, "tool_mode": true } ], "field_order": [ "agent_llm", "max_tokens", "model_kwargs", "json_mode", "model_name", "openai_api_base", "api_key", "temperature", "seed", "system_prompt", "tools", "input_value", "handle_parsing_errors", "verbose", "max_iterations", "agent_description", "memory", "sender", "sender_name", "n_messages", "session_id", "order", "template", "add_current_date_tool" ], "beta": false, "legacy": false, "edited": false, "metadata": {}, "tool_mode": false, "lf_version": "1.1.4.post1" }, "showNode": true, "type": "Agent", "id": "Agent-CjuzA" }, "selected": false, "measured": { "width": 320, "height": 703 }, "dragging": false } ], "edges": [ { "source": "Prompt-CLQNW", "sourceHandle": "{œdataTypeœ:œPromptœ,œidœ:œPrompt-CLQNWœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}", "target": "Agent-6ilGB", "targetHandle": "{œfieldNameœ:œsystem_promptœ,œidœ:œAgent-6ilGBœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "system_prompt", "id": "Agent-6ilGB", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Prompt", "id": "Prompt-CLQNW", "name": "prompt", "output_types": [ "Message" ] } }, "id": "xy-edge__Prompt-CLQNW{œdataTypeœ:œPromptœ,œidœ:œPrompt-CLQNWœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-Agent-6ilGB{œfieldNameœ:œsystem_promptœ,œidœ:œAgent-6ilGBœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "ChatInput-2x8vF", "sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-2x8vFœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}", "target": "Agent-6ilGB", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-6ilGBœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "input_value", "id": "Agent-6ilGB", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "ChatInput", "id": "ChatInput-2x8vF", "name": "message", "output_types": [ "Message" ] } }, "id": "xy-edge__ChatInput-2x8vF{œdataTypeœ:œChatInputœ,œidœ:œChatInput-2x8vFœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-6ilGB{œfieldNameœ:œinput_valueœ,œidœ:œAgent-6ilGBœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "Agent-6ilGB", "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-6ilGBœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", "target": "Agent-e7sUF", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-e7sUFœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "input_value", "id": "Agent-e7sUF", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Agent", "id": "Agent-6ilGB", "name": "response", "output_types": [ "Message" ] } }, "id": "xy-edge__Agent-6ilGB{œdataTypeœ:œAgentœ,œidœ:œAgent-6ilGBœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-Agent-e7sUF{œfieldNameœ:œinput_valueœ,œidœ:œAgent-e7sUFœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "Agent-e7sUF", "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-e7sUFœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", "target": "Agent-womuY", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-womuYœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "input_value", "id": "Agent-womuY", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Agent", "id": "Agent-e7sUF", "name": "response", "output_types": [ "Message" ] } }, "id": "xy-edge__Agent-e7sUF{œdataTypeœ:œAgentœ,œidœ:œAgent-e7sUFœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-Agent-womuY{œfieldNameœ:œinput_valueœ,œidœ:œAgent-womuYœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "ComposioAPI-RfpkY", "sourceHandle": "{œdataTypeœ:œComposioAPIœ,œidœ:œComposioAPI-RfpkYœ,œnameœ:œtoolsœ,œoutput_typesœ:[œToolœ]}", "target": "Agent-womuY", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgent-womuYœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "data": { "targetHandle": { "fieldName": "tools", "id": "Agent-womuY", "inputTypes": [ "Tool" ], "type": "other" }, "sourceHandle": { "dataType": "ComposioAPI", "id": "ComposioAPI-RfpkY", "name": "tools", "output_types": [ "Tool" ] } }, "id": "xy-edge__ComposioAPI-RfpkY{œdataTypeœ:œComposioAPIœ,œidœ:œComposioAPI-RfpkYœ,œnameœ:œtoolsœ,œoutput_typesœ:[œToolœ]}-Agent-womuY{œfieldNameœ:œtoolsœ,œidœ:œAgent-womuYœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "animated": false, "className": "" }, { "source": "Agent-womuY", "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-womuYœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", "target": "Agent-g9eV8", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-g9eV8œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "input_value", "id": "Agent-g9eV8", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Agent", "id": "Agent-womuY", "name": "response", "output_types": [ "Message" ] } }, "id": "xy-edge__Agent-womuY{œdataTypeœ:œAgentœ,œidœ:œAgent-womuYœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-Agent-g9eV8{œfieldNameœ:œinput_valueœ,œidœ:œAgent-g9eV8œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "Agent-g9eV8", "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-g9eV8œ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", "target": "Prompt-Od4Ay", "targetHandle": "{œfieldNameœ:œrecommendationsœ,œidœ:œPrompt-Od4Ayœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "recommendations", "id": "Prompt-Od4Ay", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Agent", "id": "Agent-g9eV8", "name": "response", "output_types": [ "Message" ] } }, "id": "xy-edge__Agent-g9eV8{œdataTypeœ:œAgentœ,œidœ:œAgent-g9eV8œ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-Prompt-Od4Ay{œfieldNameœ:œrecommendationsœ,œidœ:œPrompt-Od4Ayœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "Agent-womuY", "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-womuYœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", "target": "Prompt-Od4Ay", "targetHandle": "{œfieldNameœ:œoriginalœ,œidœ:œPrompt-Od4Ayœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "original", "id": "Prompt-Od4Ay", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Agent", "id": "Agent-womuY", "name": "response", "output_types": [ "Message" ] } }, "id": "xy-edge__Agent-womuY{œdataTypeœ:œAgentœ,œidœ:œAgent-womuYœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-Prompt-Od4Ay{œfieldNameœ:œoriginalœ,œidœ:œPrompt-Od4Ayœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "Prompt-Od4Ay", "sourceHandle": "{œdataTypeœ:œPromptœ,œidœ:œPrompt-Od4Ayœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}", "target": "Agent-CjuzA", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-CjuzAœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "input_value", "id": "Agent-CjuzA", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Prompt", "id": "Prompt-Od4Ay", "name": "prompt", "output_types": [ "Message" ] } }, "id": "xy-edge__Prompt-Od4Ay{œdataTypeœ:œPromptœ,œidœ:œPrompt-Od4Ayœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-Agent-CjuzA{œfieldNameœ:œinput_valueœ,œidœ:œAgent-CjuzAœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" }, { "source": "Agent-CjuzA", "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-CjuzAœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", "target": "ChatOutput-IIhYR", "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-IIhYRœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "data": { "targetHandle": { "fieldName": "input_value", "id": "ChatOutput-IIhYR", "inputTypes": [ "Message" ], "type": "str" }, "sourceHandle": { "dataType": "Agent", "id": "Agent-CjuzA", "name": "response", "output_types": [ "Message" ] } }, "id": "xy-edge__Agent-CjuzA{œdataTypeœ:œAgentœ,œidœ:œAgent-CjuzAœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-IIhYR{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-IIhYRœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "animated": false, "className": "" } ], "viewport": { "x": -929.974644550826, "y": 150.8199413895539, "zoom": 0.5555543643275489 } }, "description": "Catalyzing Business Growth through Conversational AI.", "name": "AgentFlow", "last_tested_version": "1.1.4.post1", "endpoint_name": null, "is_component": false }