79 | Provide a topic of interest, and our intelligent agents will
80 | search the internet to generate a comprehensive custom report
81 | tailored just for you.
82 |
27 | {action}
28 |
29 |
30 | );
31 | })}
32 |
33 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/components/ui/toggle-group.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import * as React from 'react';
4 | import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
5 | import { type VariantProps } from 'class-variance-authority';
6 |
7 | import { cn } from '@/lib/utils';
8 | import { toggleVariants } from '@/components/ui/toggle';
9 |
10 | const ToggleGroupContext = React.createContext<
11 | VariantProps
12 | >({
13 | size: 'default',
14 | variant: 'default',
15 | });
16 |
17 | const ToggleGroup = React.forwardRef<
18 | React.ElementRef,
19 | React.ComponentPropsWithoutRef &
20 | VariantProps
21 | >(({ className, variant, size, children, ...props }, ref) => (
22 |
27 |
28 | {children}
29 |
30 |
31 | ));
32 |
33 | ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
34 |
35 | const ToggleGroupItem = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef &
38 | VariantProps
39 | >(({ className, children, variant, size, ...props }, ref) => {
40 | const context = React.useContext(ToggleGroupContext);
41 |
42 | return (
43 |
54 | {children}
55 |
56 | );
57 | });
58 |
59 | ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
60 |
61 | export { ToggleGroup, ToggleGroupItem };
62 |
--------------------------------------------------------------------------------
/components/ui/toggle.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import * as React from 'react';
4 | import * as TogglePrimitive from '@radix-ui/react-toggle';
5 | import { cva, type VariantProps } from 'class-variance-authority';
6 |
7 | import { cn } from '@/lib/utils';
8 |
9 | const toggleVariants = cva(
10 | 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
11 | {
12 | variants: {
13 | variant: {
14 | default: 'bg-transparent',
15 | outline:
16 | 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground',
17 | },
18 | size: {
19 | default: 'h-10 px-3',
20 | sm: 'h-9 px-2.5',
21 | lg: 'h-11 px-5',
22 | },
23 | },
24 | defaultVariants: {
25 | variant: 'default',
26 | size: 'default',
27 | },
28 | }
29 | );
30 |
31 | const Toggle = React.forwardRef<
32 | React.ElementRef,
33 | React.ComponentPropsWithoutRef &
34 | VariantProps
35 | >(({ className, variant, size, ...props }, ref) => (
36 |
41 | ));
42 |
43 | Toggle.displayName = TogglePrimitive.Root.displayName;
44 |
45 | export { Toggle, toggleVariants };
46 |
--------------------------------------------------------------------------------
/components/ui/tooltip.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import * as React from 'react';
4 | import * as TooltipPrimitive from '@radix-ui/react-tooltip';
5 |
6 | import { cn } from '@/lib/utils';
7 |
8 | const TooltipProvider = TooltipPrimitive.Provider;
9 |
10 | const Tooltip = TooltipPrimitive.Root;
11 |
12 | const TooltipTrigger = TooltipPrimitive.Trigger;
13 |
14 | const TooltipContent = React.forwardRef<
15 | React.ElementRef,
16 | React.ComponentPropsWithoutRef
17 | >(({ className, sideOffset = 4, ...props }, ref) => (
18 |
27 | ));
28 | TooltipContent.displayName = TooltipPrimitive.Content.displayName;
29 |
30 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
31 |
--------------------------------------------------------------------------------
/flows/NewsLetter MultiAgent.json:
--------------------------------------------------------------------------------
1 | {"id":"404dae1f-d8eb-477b-b6fc-fefbfd37d7ef","data":{"nodes":[{"id":"News API Request-Y1ShE","type":"genericNode","position":{"x":403.76109665247327,"y":614.936112084666},"data":{"node":{"template":{"_type":"Component","query_params":{"tool_mode":true,"trace_as_metadata":true,"list":false,"trace_as_input":true,"required":false,"placeholder":"","show":true,"name":"query_params","value":"","display_name":"Query Parameters","advanced":false,"input_types":["Data"],"dynamic":false,"info":"The query parameters to append to the URL.","title_case":false,"type":"other","_input_type":"DataInput"},"body":{"trace_as_input":true,"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"body","value":{},"display_name":"Body","advanced":false,"input_types":["Data"],"dynamic":false,"info":"The body to send with the request as a dictionary (for POST, PATCH, PUT). This is populated when using the CURL field.","title_case":false,"type":"NestedDict","_input_type":"NestedDictInput"},"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"import asyncio\nimport json\nfrom typing import Any\nfrom urllib.parse import parse_qsl, urlencode, urlparse, urlunparse\n\nimport httpx\nfrom loguru import logger\n\nfrom langflow.base.curl.parse import parse_context\nfrom langflow.custom import Component\nfrom langflow.io import DataInput, DropdownInput, IntInput, MessageTextInput, NestedDictInput, Output\nfrom langflow.schema import Data\nfrom langflow.schema.dotdict import dotdict\n\n\nclass APIRequestComponent(Component):\n display_name = \"News API Request\"\n description = (\n \"This component allows you to make HTTP requests to one or more URLs. \"\n \"You can provide headers and body as either dictionaries or Data objects. \"\n \"Additionally, you can append query parameters to the URLs.\\n\\n\"\n \"**Note:** Check advanced options for more settings.\"\n )\n icon = \"Globe\"\n name = \"News API Request\"\n\n inputs = [\n MessageTextInput(\n name=\"urls\",\n display_name=\"URLs\",\n is_list=True,\n info=\"Enter one or more URLs, separated by commas.\",\n ),\n MessageTextInput(\n name=\"curl\",\n display_name=\"cURL\",\n info=\"Paste a curl command to populate the fields. \"\n \"This will fill in the dictionary fields for headers and body.\",\n advanced=False,\n refresh_button=True,\n real_time_refresh=True,\n tool_mode=True,\n ),\n DropdownInput(\n name=\"method\",\n display_name=\"Method\",\n options=[\"GET\", \"POST\", \"PATCH\", \"PUT\"],\n value=\"GET\",\n info=\"The HTTP method to use (GET, POST, PATCH, PUT).\",\n ),\n NestedDictInput(\n name=\"headers\",\n display_name=\"Headers\",\n info=\"The headers to send with the request as a dictionary. This is populated when using the CURL field.\",\n input_types=[\"Data\"],\n ),\n NestedDictInput(\n name=\"body\",\n display_name=\"Body\",\n info=\"The body to send with the request as a dictionary (for POST, PATCH, PUT). \"\n \"This is populated when using the CURL field.\",\n input_types=[\"Data\"],\n ),\n DataInput(\n name=\"query_params\",\n display_name=\"Query Parameters\",\n info=\"The query parameters to append to the URL.\",\n tool_mode=True,\n ),\n IntInput(\n name=\"timeout\",\n display_name=\"Timeout\",\n value=5,\n info=\"The timeout to use for the request.\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"make_requests\"),\n ]\n\n def parse_curl(self, curl: str, build_config: dotdict) -> dotdict:\n try:\n parsed = parse_context(curl)\n build_config[\"urls\"][\"value\"] = [parsed.url]\n build_config[\"method\"][\"value\"] = parsed.method.upper()\n build_config[\"headers\"][\"value\"] = dict(parsed.headers)\n\n if parsed.data:\n try:\n json_data = json.loads(parsed.data)\n build_config[\"body\"][\"value\"] = json_data\n except json.JSONDecodeError:\n logger.exception(\"Error decoding JSON data\")\n else:\n build_config[\"body\"][\"value\"] = {}\n except Exception as exc:\n msg = f\"Error parsing curl: {exc}\"\n logger.exception(msg)\n raise ValueError(msg) from exc\n return build_config\n\n def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):\n if field_name == \"curl\" and field_value:\n build_config = self.parse_curl(field_value, build_config)\n return build_config\n\n async def make_request(\n self,\n client: httpx.AsyncClient,\n method: str,\n url: str,\n headers: dict | None = None,\n body: dict | None = None,\n timeout: int = 5,\n ) -> Data:\n method = method.upper()\n if method not in {\"GET\", \"POST\", \"PATCH\", \"PUT\", \"DELETE\"}:\n msg = f\"Unsupported method: {method}\"\n raise ValueError(msg)\n\n if isinstance(body, str) and body:\n try:\n body = json.loads(body)\n except Exception as e:\n msg = f\"Error decoding JSON data: {e}\"\n logger.exception(msg)\n body = None\n raise ValueError(msg) from e\n\n data = body or None\n\n try:\n response = await client.request(method, url, headers=headers, json=data, timeout=timeout)\n try:\n result = response.json()\n except Exception: # noqa: BLE001\n logger.opt(exception=True).debug(\"Error decoding JSON response\")\n result = response.text\n return Data(\n data={\n \"source\": url,\n \"headers\": headers,\n \"status_code\": response.status_code,\n \"result\": result,\n },\n )\n except httpx.TimeoutException:\n return Data(\n data={\n \"source\": url,\n \"headers\": headers,\n \"status_code\": 408,\n \"error\": \"Request timed out\",\n },\n )\n except Exception as exc: # noqa: BLE001\n logger.opt(exception=True).debug(f\"Error making request to {url}\")\n return Data(\n data={\n \"source\": url,\n \"headers\": headers,\n \"status_code\": 500,\n \"error\": str(exc),\n },\n )\n\n def add_query_params(self, url: str, params: dict) -> str:\n url_parts = list(urlparse(url))\n query = dict(parse_qsl(url_parts[4]))\n query.update(params)\n url_parts[4] = urlencode(query)\n return urlunparse(url_parts)\n\n async def make_requests(self) -> list[Data]:\n method = self.method\n urls = [url.strip() for url in self.urls if url.strip()]\n curl = self.curl\n headers = self.headers or {}\n body = self.body or {}\n timeout = self.timeout\n\n if isinstance(self.query_params, str):\n query_params = dict(parse_qsl(self.query_params))\n else:\n query_params = self.query_params.data if self.query_params else {}\n\n if curl:\n self._build_config = self.parse_curl(curl, dotdict())\n\n if isinstance(headers, Data):\n headers = headers.data\n\n if isinstance(body, Data):\n body = body.data\n\n bodies = [body] * len(urls)\n\n urls = [self.add_query_params(url, query_params) for url in urls]\n\n async with httpx.AsyncClient() as client:\n results = await asyncio.gather(\n *[\n self.make_request(client, method, u, headers, rec, timeout)\n for u, rec in zip(urls, bodies, strict=True)\n ]\n )\n self.status = results\n return results\n","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":true,"dynamic":true,"info":"","load_from_db":false,"title_case":false},"curl":{"tool_mode":true,"trace_as_input":true,"trace_as_metadata":true,"load_from_db":false,"list":false,"required":false,"placeholder":"","show":true,"name":"curl","value":"","display_name":"cURL","advanced":false,"input_types":["Message"],"dynamic":false,"info":"Paste a curl command to populate the fields. This will fill in the dictionary fields for headers and body.","real_time_refresh":true,"refresh_button":true,"title_case":false,"type":"str","_input_type":"MessageTextInput"},"headers":{"trace_as_input":true,"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"headers","value":{"Authorization":"Bearer"},"display_name":"Headers","advanced":false,"input_types":["Data"],"dynamic":false,"info":"The headers to send with the request as a dictionary. This is populated when using the CURL field.","title_case":false,"type":"NestedDict","_input_type":"NestedDictInput"},"method":{"tool_mode":false,"trace_as_metadata":true,"options":["GET","POST","PATCH","PUT"],"combobox":false,"required":false,"placeholder":"","show":true,"name":"method","value":"GET","display_name":"Method","advanced":false,"dynamic":false,"info":"The HTTP method to use (GET, POST, PATCH, PUT).","title_case":false,"type":"str","_input_type":"DropdownInput"},"timeout":{"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"timeout","value":5,"display_name":"Timeout","advanced":false,"dynamic":false,"info":"The timeout to use for the request.","title_case":false,"type":"int","_input_type":"IntInput"},"urls":{"tool_mode":false,"trace_as_input":true,"trace_as_metadata":true,"load_from_db":false,"list":true,"required":false,"placeholder":"","show":true,"name":"urls","value":["https://newsapi.org/v2/everything"],"display_name":"URLs","advanced":false,"input_types":["Message"],"dynamic":false,"info":"Enter one or more URLs, separated by commas.","title_case":false,"type":"str","_input_type":"MessageTextInput"}},"description":"This component allows you to make HTTP requests to one or more URLs. You can provide headers and body as either dictionaries or Data objects. Additionally, you can append query parameters to the URLs.\n\n**Note:** Check advanced options for more settings.","icon":"Globe","base_classes":["Data"],"display_name":"News API ","documentation":"","custom_fields":{},"output_types":[],"pinned":false,"conditional_paths":[],"frozen":false,"outputs":[{"types":["Tool"],"selected":"Tool","name":"component_as_tool","hidden":null,"display_name":"Toolset","method":"to_toolkit","value":"__UNDEFINED__","cache":true,"required_inputs":null}],"field_order":["urls","curl","method","headers","body","query_params","timeout"],"beta":false,"legacy":false,"edited":true,"metadata":{},"lf_version":"1.1.0"},"type":"News API Request","id":"News API Request-Y1ShE"},"selected":false,"width":320,"height":860,"positionAbsolute":{"x":403.76109665247327,"y":614.936112084666},"dragging":false},{"id":"ComposioAPI-xrwhc","type":"genericNode","position":{"x":200.8647853537292,"y":2116.5767795304528},"data":{"node":{"template":{"_type":"Component","action_names":{"trace_as_metadata":true,"options":["GMAIL_ADD_LABEL_TO_EMAIL","GMAIL_CREATE_EMAIL_DRAFT","GMAIL_CREATE_LABEL","GMAIL_FETCH_EMAILS","GMAIL_FETCH_MESSAGE_BY_THREAD_ID","GMAIL_GET_ATTACHMENT","GMAIL_LIST_LABELS","GMAIL_LIST_THREADS","GMAIL_REPLY_TO_THREAD","GMAIL_SEND_EMAIL"],"combobox":false,"list":true,"required":false,"placeholder":"","show":true,"name":"action_names","value":["GMAIL_SEND_EMAIL"],"display_name":"Actions to use","advanced":false,"dynamic":false,"info":"The actions to pass to agent to execute","title_case":false,"type":"str","_input_type":"MultiselectInput"},"api_key":{"load_from_db":true,"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/introduction/foundations/howtos/get_api_key","refresh_button":true,"title_case":false,"password":true,"type":"str","_input_type":"SecretStrInput"},"app_names":{"tool_mode":false,"trace_as_metadata":true,"options":["GMAIL_CONNECTED","GOOGLECALENDAR_CONNECTED","YOUTUBE_CONNECTED","APALEO","APIFY","ASANA","ATTIO","BITBUCKET","BREVO","BROWSERBASE_TOOL","BROWSER_TOOL","CLICKUP","CODEINTERPRETER","CODE_FORMAT_TOOL","CODE_GREP_TOOL","CODE_INDEX_TOOL","CODE_MAP_TOOL","COMPOSIO","DISCORD","DROPBOX","ELEVENLABS","EMBED_TOOL","EXA","FIGMA","FILETOOL","FIRECRAWL","GIT","GITHUB","GITLAB","GOOGLEDOCS","GOOGLEDRIVE","GOOGLEMEET","GOOGLESHEETS","GOOGLETASKS","GREPTILE","HACKERNEWS","HEROKU","HISTORY_FETCHER","HUBSPOT","IMAGE_ANALYSER","INDUCED_AI","JIRA","KLAVIYO","LINEAR","LISTENNOTES","MATHEMATICAL","MULTIONAI","NASA","NOTION","OKTA","PAGERDUTY","PERPLEXITYAI","PIPEDRIVE","POSTHOG","RAGTOOL","SCHEDULER","SERPAPI","SHELLTOOL","SLACK","SLACKBOT","SNOWFLAKE","SOUNDCLOUD","SPIDERTOOL","SPLITWISE","SPOTIFY","SQLTOOL","STRAVA","TASKADE","TAVILY","TRELLO","TWILIO","TWITTER","TYPEFORM","WEATHERMAP","WEBTOOL","WHATSAPP","WORKABLE","WORKSPACE_TOOL","YOUSEARCH","ZENDESK","ZEPTOOL","ZOOM"],"combobox":false,"required":false,"placeholder":"","show":true,"name":"app_names","value":"GMAIL_CONNECTED","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_config":{"trace_as_metadata":true,"load_from_db":false,"list":false,"required":false,"placeholder":"","show":true,"name":"auth_status_config","value":"GMAIL CONNECTED","display_name":"Auth status","advanced":false,"dynamic":false,"info":"Open link or enter api key. Then refresh button","refresh_button":true,"title_case":false,"type":"str","_input_type":"StrInput"},"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"from collections.abc import Sequence\nfrom typing import Any\n\nfrom composio_langchain import Action, App, ComposioToolSet\nfrom langchain_core.tools import Tool\nfrom loguru import logger\nfrom typing_extensions import override\n\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import DropdownInput, MessageTextInput, MultiselectInput, SecretStrInput, StrInput\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 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 refresh_button=True,\n info=\"Refer to https://docs.composio.dev/introduction/foundations/howtos/get_api_key\",\n ),\n DropdownInput(\n name=\"app_names\",\n display_name=\"App Name\",\n options=list(App.__annotations__),\n value=\"\",\n info=\"The app name to use. Please refresh after selecting app name\",\n refresh_button=True,\n ),\n MultiselectInput(\n name=\"action_names\",\n display_name=\"Actions to use\",\n required=False,\n options=[],\n value=[],\n info=\"The actions to pass to agent to execute\",\n ),\n StrInput(\n name=\"auth_status_config\",\n display_name=\"Auth status\",\n value=\"\",\n refresh_button=True,\n info=\"Open link or enter api key. Then refresh button\",\n ),\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.\n \"\"\"\n toolset = self._build_wrapper()\n entity = toolset.client.get_entity(id=self.entity_id)\n try:\n entity.get_connection(app=app)\n except Exception: # noqa: BLE001\n logger.opt(exception=True).debug(\"Authorization error\")\n return self._handle_authorization_failure(toolset, entity, app)\n\n return f\"{app} CONNECTED\"\n\n def _handle_authorization_failure(self, toolset: ComposioToolSet, entity: Any, app: str) -> str:\n \"\"\"Handles the authorization failure by attempting to process API key auth or initiate default connection.\n\n Args:\n toolset (ComposioToolSet): The toolset instance.\n entity (Any): The entity instance.\n app (str): The app name.\n\n Returns:\n str: The result of the authorization failure message.\n \"\"\"\n try:\n auth_schemes = toolset.client.apps.get(app).auth_schemes\n if auth_schemes[0].auth_mode == \"API_KEY\":\n return self._process_api_key_auth(entity, app)\n return self._initiate_default_connection(entity, app)\n except Exception: # noqa: BLE001\n logger.exception(\"Authorization error\")\n return \"Error\"\n\n def _process_api_key_auth(self, entity: Any, app: str) -> str:\n \"\"\"Processes the API key authentication.\n\n Args:\n entity (Any): The entity instance.\n app (str): The app name.\n\n Returns:\n str: The status of the API key authentication.\n \"\"\"\n auth_status_config = self.auth_status_config\n is_url = \"http\" in auth_status_config or \"https\" in auth_status_config\n is_different_app = \"CONNECTED\" in auth_status_config and app not in auth_status_config\n is_default_api_key_message = \"API Key\" in auth_status_config\n\n if is_different_app or is_url or is_default_api_key_message:\n return \"Enter API Key\"\n if not is_default_api_key_message:\n entity.initiate_connection(\n app_name=app,\n auth_mode=\"API_KEY\",\n auth_config={\"api_key\": self.auth_status_config},\n use_composio_auth=False,\n force_new_integration=True,\n )\n return f\"{app} CONNECTED\"\n return \"Enter API Key\"\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 _update_app_names_with_connected_status(self, build_config: dict) -> dict:\n connected_app_names = self._get_connected_app_names_for_entity()\n\n app_names = [\n f\"{app_name}_CONNECTED\" for app_name in App.__annotations__ if app_name.lower() in connected_app_names\n ]\n non_connected_app_names = [\n app_name for app_name in App.__annotations__ if app_name.lower() not in connected_app_names\n ]\n build_config[\"app_names\"][\"options\"] = app_names + non_connected_app_names\n build_config[\"app_names\"][\"value\"] = app_names[0] if app_names else \"\"\n return build_config\n\n def _get_normalized_app_name(self) -> str:\n return self.app_names.replace(\"_CONNECTED\", \"\").replace(\"_connected\", \"\")\n\n @override\n def update_build_config(self, build_config: dict, field_value: Any, field_name: str | None = None) -> dict:\n if field_name == \"api_key\":\n if hasattr(self, \"api_key\") and self.api_key != \"\":\n build_config = self._update_app_names_with_connected_status(build_config)\n return build_config\n\n if field_name in {\"app_names\", \"auth_status_config\"}:\n if hasattr(self, \"api_key\") and self.api_key != \"\":\n build_config[\"auth_status_config\"][\"value\"] = self._check_for_authorization(\n self._get_normalized_app_name()\n )\n all_action_names = list(Action.__annotations__)\n app_action_names = [\n action_name\n for action_name in all_action_names\n if action_name.lower().startswith(self._get_normalized_app_name().lower() + \"_\")\n ]\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 return build_config\n\n def build_tool(self) -> Sequence[Tool]:\n composio_toolset = self._build_wrapper()\n return composio_toolset.get_tools(actions=self.action_names)\n\n def _build_wrapper(self) -> ComposioToolSet:\n return ComposioToolSet(api_key=self.api_key)\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,"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"}},"description":"Use Composio toolset to run actions with your agent","icon":"Composio","base_classes":["Data","Tool"],"display_name":"Composio Tools","documentation":"https://docs.composio.dev","custom_fields":{},"output_types":[],"pinned":false,"conditional_paths":[],"frozen":false,"outputs":[{"types":["Data"],"selected":"Data","name":"api_run_model","hidden":null,"display_name":"Data","method":"run_model","value":"__UNDEFINED__","cache":true,"required_inputs":[]},{"types":["Tool"],"selected":"Tool","name":"api_build_tool","hidden":null,"display_name":"Tool","method":"build_tool","value":"__UNDEFINED__","cache":true,"required_inputs":["api_key"]}],"field_order":["entity_id","api_key","app_names","action_names","auth_status_config"],"beta":false,"legacy":false,"edited":false,"metadata":{},"tool_mode":false,"category":"toolkits","key":"ComposioAPI","lf_version":"1.1.0"},"type":"ComposioAPI","id":"ComposioAPI-xrwhc"},"selected":false,"width":320,"height":561,"positionAbsolute":{"x":200.8647853537292,"y":2116.5767795304528},"dragging":false},{"id":"ChatInput-6fofq","type":"genericNode","position":{"x":27.33437373450431,"y":1321.5314549677698},"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,"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,"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,"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 DropdownInput, FileInput, MessageTextInput, MultilineInput, Output\nfrom langflow.schema.message import Message\nfrom langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_USER, MESSAGE_SENDER_USER\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\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n value=\"\",\n info=\"Message to be passed as input.\",\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 def message_response(self) -> Message:\n _background_color = self.background_color\n _text_color = self.text_color\n _icon = self.chat_icon\n message = Message(\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={\"background_color\": _background_color, \"text_color\": _text_color, \"icon\": _icon},\n )\n if self.session_id and isinstance(message, Message) and self.should_store_message:\n stored_message = 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,"required":false,"placeholder":"","show":true,"name":"input_value","value":"Gather news on Tesla","display_name":"Text","advanced":false,"input_types":["Message"],"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"],"combobox":false,"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,"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,"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":{"trace_as_metadata":true,"list":false,"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,"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":"","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}],"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.0"},"type":"ChatInput","id":"ChatInput-6fofq"},"selected":false,"width":320,"height":233,"positionAbsolute":{"x":27.33437373450431,"y":1321.5314549677698},"dragging":false},{"id":"NewsAgent-7KSUU","type":"genericNode","position":{"x":806.8698124675443,"y":822.3671923109437},"data":{"node":{"template":{"_type":"Component","memory":{"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"memory","value":"","display_name":"External Memory","advanced":true,"input_types":["BaseChatMessageHistory"],"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,"required":false,"placeholder":"","show":true,"name":"tools","value":"","display_name":"Tools","advanced":false,"input_types":["Tool","BaseTool","StructuredTool"],"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":{"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"add_current_date_tool","value":true,"display_name":"Add tool 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,"required":false,"placeholder":"","show":true,"name":"agent_description","value":"A helpful assistant with access to the following tools:","display_name":"Agent Description","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.","title_case":false,"type":"str","_input_type":"MultilineInput"},"agent_llm":{"tool_mode":false,"trace_as_metadata":true,"options":["Amazon Bedrock","Anthropic","Azure OpenAI","Groq","NVIDIA","OpenAI","Custom"],"combobox":false,"required":false,"placeholder":"","show":true,"name":"agent_llm","value":"OpenAI","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 ALL_PROVIDER_FIELDS, MODEL_PROVIDERS_DICT\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.io import BoolInput, DropdownInput, MultilineInput, Output\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 = \"NewsAgent\"\n description: str = \"Agent that is used to search News from News API, with help of various Tools\"\n icon = \"bot\"\n beta = False\n name = \"NewsAgent\"\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=\"Add tool 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 llm_model, display_name = self.get_llm()\n self.model_name = get_model_name(llm_model, display_name=display_name)\n if llm_model is None:\n msg = \"No language model selected\"\n raise ValueError(msg)\n self.chat_history = self.get_memory_data()\n\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n # Convert CurrentDateComponent to a StructuredTool\n current_date_tool = CurrentDateComponent().to_toolkit()[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 ValueError(msg)\n\n if not self.tools:\n msg = \"Tools are required to run the agent.\"\n raise ValueError(msg)\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 return await self.run_agent(agent)\n\n 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\n return MemoryComponent().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 self._build_llm_model(component_class, inputs, prefix), display_name\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 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 def update_build_config(self, build_config: dotdict, field_value: str, field_name: str | None = None) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name == \"agent_llm\":\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 = component_class.update_build_config(build_config, field_value, field_name)\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 isinstance(self.agent_llm, str) and self.agent_llm in MODEL_PROVIDERS_DICT:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"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 = component_class.update_build_config(build_config, field_value, field_name)\n\n return build_config\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":{"trace_as_metadata":true,"list":false,"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,"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":{"trace_as_metadata":true,"list":false,"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":{"trace_as_metadata":true,"list":false,"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":false,"trace_as_metadata":true,"options":["Ascending","Descending"],"combobox":false,"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"],"combobox":false,"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,"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,"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,"required":false,"placeholder":"","show":true,"name":"system_prompt","value":"You are a helpful assistant that can use tools to answer questions and perform tasks. Use the Header from the Tool. Sample Query Paramters in URL are : the format for Query Param is : Data input with keys q, from and sortBy as Keys from is the date in format: yyyy-mm-dd Also Always request the with a previous day date if the current date news is requested. Since News API have a 24 hours delay. Use the current data to get the date, if no time zone given use any time zone in America like US/Eastern. Make sure all the news is sort by popularity and it is in english. Draft a query data and use the API request tool to get the data Make sure the reply have relevant urls, image urls, titles tags etc. Give the response in JSON and not in Markdown.","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,"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":{"trace_as_metadata":true,"list":false,"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_tokens":{"trace_as_metadata":true,"range_spec":{"step_type":"float","min":0,"max":128000,"step":0.1},"list":false,"required":false,"placeholder":"","show":true,"name":"max_tokens","value":"","display_name":"Max Tokens","advanced":true,"input_types":[],"dynamic":false,"info":"The maximum number of tokens to generate. Set to 0 for unlimited tokens.","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"int","_input_type":"IntInput"},"model_kwargs":{"trace_as_input":true,"list":false,"required":false,"placeholder":"","show":true,"name":"model_kwargs","value":{},"display_name":"Model Kwargs","advanced":true,"input_types":[],"dynamic":false,"info":"Additional keyword arguments to pass to the model.","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"dict","_input_type":"DictInput"},"json_mode":{"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"json_mode","value":false,"display_name":"JSON Mode","advanced":true,"input_types":[],"dynamic":false,"info":"If True, it will output JSON regardless of passing a schema.","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"bool","_input_type":"BoolInput"},"output_schema":{"trace_as_input":true,"list":true,"required":false,"placeholder":"","show":true,"name":"output_schema","value":{},"display_name":"Schema","advanced":true,"input_types":[],"dynamic":false,"info":"The schema for the Output of the model. You must pass the word JSON in the prompt. If left blank, JSON mode will be disabled. [DEPRECATED]","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"dict","_input_type":"DictInput"},"model_name":{"tool_mode":false,"trace_as_metadata":true,"options":["gpt-4o-mini","gpt-4o","gpt-4-turbo","gpt-4-turbo-preview","gpt-4","gpt-3.5-turbo","gpt-3.5-turbo-0125"],"combobox":false,"required":false,"placeholder":"","show":true,"name":"model_name","value":"gpt-4o-mini","display_name":"Model Name","advanced":false,"input_types":[],"dynamic":false,"info":"","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"str","_input_type":"DropdownInput"},"openai_api_base":{"trace_as_metadata":true,"load_from_db":false,"list":false,"required":false,"placeholder":"","show":true,"name":"openai_api_base","value":"","display_name":"OpenAI API Base","advanced":true,"input_types":[],"dynamic":false,"info":"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"str","_input_type":"StrInput"},"api_key":{"load_from_db":true,"required":false,"placeholder":"","show":true,"name":"api_key","value":"","display_name":"OpenAI API Key","advanced":false,"input_types":["Message"],"dynamic":false,"info":"The OpenAI API Key to use for the OpenAI model.","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"password":true,"type":"str","_input_type":"SecretStrInput"},"temperature":{"trace_as_metadata":true,"range_spec":null,"list":false,"required":false,"placeholder":"","show":true,"name":"temperature","value":0.1,"display_name":"Temperature","advanced":true,"input_types":[],"dynamic":false,"info":"","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"float","_input_type":"FloatInput"},"seed":{"trace_as_metadata":true,"range_spec":null,"list":false,"required":false,"placeholder":"","show":true,"name":"seed","value":1,"display_name":"Seed","advanced":true,"input_types":[],"dynamic":false,"info":"The seed controls the reproducibility of the job.","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"int","_input_type":"IntInput"},"output_parser":{"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"output_parser","value":"","display_name":"Output Parser","advanced":true,"input_types":["OutputParser"],"dynamic":false,"info":"The parser to use to parse the output of the model","real_time_refresh":null,"refresh_button":null,"refresh_button_text":null,"title_case":false,"type":"other","_input_type":"HandleInput"}},"description":"Agent that is used to search News from News API, with help of various Tools","icon":"bot","base_classes":["Message"],"display_name":"NewsAgent","documentation":"","custom_fields":{},"output_types":[],"pinned":false,"conditional_paths":[],"frozen":false,"outputs":[{"types":["Tool"],"selected":"Tool","name":"component_as_tool","hidden":null,"display_name":"Toolset","method":"to_toolkit","value":"__UNDEFINED__","cache":true,"required_inputs":null}],"field_order":["agent_llm","max_tokens","model_kwargs","json_mode","output_schema","model_name","openai_api_base","api_key","temperature","seed","output_parser","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":true,"metadata":{},"tool_mode":false,"lf_version":"1.1.0"},"type":"NewsAgent","id":"NewsAgent-7KSUU"},"selected":false,"width":320,"height":647,"positionAbsolute":{"x":806.8698124675443,"y":822.3671923109437},"dragging":false},{"id":"NewsLetterAgent-AuPCR","type":"genericNode","position":{"x":828.7566694982054,"y":2118.8319792960615},"data":{"node":{"template":{"_type":"Component","memory":{"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"memory","value":"","display_name":"External Memory","advanced":true,"input_types":["BaseChatMessageHistory"],"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,"required":false,"placeholder":"","show":true,"name":"tools","value":"","display_name":"Tools","advanced":false,"input_types":["Tool","BaseTool","StructuredTool"],"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":{"trace_as_metadata":true,"list":false,"required":false,"placeholder":"","show":true,"name":"add_current_date_tool","value":true,"display_name":"Add tool 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,"required":false,"placeholder":"","show":true,"name":"agent_description","value":"A helpful assistant with access to the following tools:","display_name":"Agent Description","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.","title_case":false,"type":"str","_input_type":"MultilineInput"},"agent_llm":{"tool_mode":false,"trace_as_metadata":true,"options":["Amazon Bedrock","Anthropic","Azure OpenAI","Groq","NVIDIA","OpenAI","Custom"],"combobox":false,"required":false,"placeholder":"","show":true,"name":"agent_llm","value":"OpenAI","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 ALL_PROVIDER_FIELDS, MODEL_PROVIDERS_DICT\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.io import BoolInput, DropdownInput, MultilineInput, Output\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 = \"NewsLetterAgent\"\n description: str = \"Agent that makes a well formatted Newsletter and uses tools to send Emails\"\n icon = \"bot\"\n beta = False\n name = \"NewsLetterAgent\"\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=\"Add tool 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 llm_model, display_name = self.get_llm()\n self.model_name = get_model_name(llm_model, display_name=display_name)\n if llm_model is None:\n msg = \"No language model selected\"\n raise ValueError(msg)\n self.chat_history = self.get_memory_data()\n\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n # Convert CurrentDateComponent to a StructuredTool\n current_date_tool = CurrentDateComponent().to_toolkit()[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 ValueError(msg)\n\n if not self.tools:\n msg = \"Tools are required to run the agent.\"\n raise ValueError(msg)\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 return await self.run_agent(agent)\n\n 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\n return MemoryComponent().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 self._build_llm_model(component_class, inputs, prefix), display_name\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 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 def update_build_config(self, build_config: dotdict, field_value: str, field_name: str | None = None) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name == \"agent_llm\":\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 = component_class.update_build_config(build_config, field_value, field_name)\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 isinstance(self.agent_llm, str) and self.agent_llm in MODEL_PROVIDERS_DICT:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"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 = component_class.update_build_config(build_config, field_value, field_name)\n\n return build_config\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":{"trace_as_metadata":true,"list":false,"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,"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":{"trace_as_metadata":true,"list":false,"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":{"trace_as_metadata":true,"list":false,"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":false,"trace_as_metadata":true,"options":["Ascending","Descending"],"combobox":false,"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"],"combobox":false,"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,"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,"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,"required":false,"placeholder":"","show":true,"name":"system_prompt","value":"To ensure images display correctly in most email clients, images must be hosted on a secure server (HTTPS) and referenced with absolute URLs. Additionally, inline styles are essential, as some email clients strip out CSS in