diff --git a/configs/agents/billing.yaml b/configs/agents/billing.yaml index 1e2d44d..2b4cc3a 100644 --- a/configs/agents/billing.yaml +++ b/configs/agents/billing.yaml @@ -11,7 +11,7 @@ system_prompt: | When the customer asks a question: 1. ALWAYS use the provided tools to retrieve accurate customer billing data: - - get_billing_info: Use this tool to get detailed billing statements based on customer, billing_start_date and billing_end_date. The value of customer should always be present and provided by the user. Filter the results if the user provides values for additional_charges, total_amount, and payment status. Use the default values if the user does not provide values for these parameters. + - get_billing_info: Use this tool to get detailed billing statements based on customer, billing_start_date and billing_end_date. The customer ID is always available. Filter the results if the user provides values for additional_charges, total_amount, and payment status. Use the default values if the user does not provide values for these parameters. - get_usage_info: Use this tool to get usage details including data, voice, and SMS usage for a specific time period. - system.ai.python_exec: Use this tool to execute python code to get the current date and month and generate the values for usage_start_date, usage_end_date, billing_start_date and billing_end_date based on the current date and month and the timeframe user asks for. diff --git a/telco_support_agent/agents/base_agent.py b/telco_support_agent/agents/base_agent.py index d851b87..1f7a912 100644 --- a/telco_support_agent/agents/base_agent.py +++ b/telco_support_agent/agents/base_agent.py @@ -413,8 +413,45 @@ def execute_tool(self, tool_name: str, args: dict) -> Any: result = self.vector_search_tools[tool_name].execute(**args) else: uc_function_name = tool_name.replace("__", ".") + # Convert None values and string null representations to SQL NULL by omitting them + cleaned_args = {} + for k, v in args.items(): + # Skip None values and string representations of null/empty + if v is None: + continue + if isinstance(v, str) and v.lower() in ("null", "none", ""): + continue + + # Convert numeric values appropriately for UC functions + if isinstance(v, int | float): + # For parameters that should be DOUBLE, always use float + if k.endswith(("_input", "_amount", "_charge", "_value")): + cleaned_args[k] = float(v) + else: + cleaned_args[k] = v + elif ( + isinstance(v, str) + and v.replace(".", "").replace("-", "").isdigit() + ): + try: + # For DOUBLE parameters, always convert to float + if k.endswith( + ("_input", "_amount", "_charge", "_value") + ): + cleaned_args[k] = float(v) + else: + cleaned_args[k] = float(v) if "." in v else int(v) + except ValueError: + cleaned_args[k] = ( + v # Keep as string if conversion fails + ) + else: + cleaned_args[k] = v + logger.debug( + f"UC function {uc_function_name}: original args {args}, cleaned args {cleaned_args}" + ) result = self.uc_client.execute_function( - function_name=uc_function_name, parameters=args + function_name=uc_function_name, parameters=cleaned_args ).value span.set_outputs(result) diff --git a/telco_support_agent/tools/billing/functions.py b/telco_support_agent/tools/billing/functions.py index 8c4ecae..451abe8 100644 --- a/telco_support_agent/tools/billing/functions.py +++ b/telco_support_agent/tools/billing/functions.py @@ -23,9 +23,9 @@ def register_get_billing_info(uc_config: UCConfig): customer STRING COMMENT 'The customer ID in the format CUS-XXXXX', billing_start_date_input STRING COMMENT 'The billing start date in YYYY-MM-DD format. Defaults to first day of current month.', billing_end_date_input STRING COMMENT 'The billing end date in YYYY-MM-DD format. Defaults to first day of next month.', - additional_charges_input DOUBLE COMMENT 'Filter on additional_charges. Must be non negative. If 0, only rows with non-NULL additional_charges are included. Can be NULL to skip filtering.', - total_amount_input DOUBLE COMMENT 'Filter on total_amount. Must be non negative. If 0, only rows with non-NULL total_amount are included. Can be NULL to skip filtering.', - status_input STRING COMMENT 'Billing status. Possible values: Paid, Unpaid, Late, Partial, All. Defaults to All. If All, return rows of all statuses.' + additional_charges_input DOUBLE DEFAULT NULL COMMENT 'Filter on additional_charges. Must be non negative. If 0, only rows with non-NULL additional_charges are included. Can be NULL to skip filtering.', + total_amount_input DOUBLE DEFAULT NULL COMMENT 'Filter on total_amount. Must be non negative. If 0, only rows with non-NULL total_amount are included. Can be NULL to skip filtering.', + status_input STRING DEFAULT 'All' COMMENT 'Billing status. Possible values: Paid, Unpaid, Late, Partial, All. Defaults to All. If All, return rows of all statuses.' ) RETURNS STRING COMMENT 'Retrieves all columns of the billing table for all rows for a customer within the specified date range, with optional filters for additional_charges, total_amount, and status. Example usage: SELECT {function_name}("CUS-10601","2025-06-01","2025-06-01",NULL,NULL,"Paid")'