holmesgpt 0.13.3a0__py3-none-any.whl → 0.14.1a0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of holmesgpt might be problematic. Click here for more details.

Files changed (82) hide show
  1. holmes/__init__.py +1 -1
  2. holmes/clients/robusta_client.py +10 -2
  3. holmes/common/env_vars.py +8 -1
  4. holmes/config.py +66 -139
  5. holmes/core/investigation.py +1 -2
  6. holmes/core/llm.py +256 -51
  7. holmes/core/models.py +2 -0
  8. holmes/core/safeguards.py +4 -4
  9. holmes/core/supabase_dal.py +14 -8
  10. holmes/core/tool_calling_llm.py +193 -176
  11. holmes/core/tools.py +260 -25
  12. holmes/core/tools_utils/data_types.py +81 -0
  13. holmes/core/tools_utils/tool_context_window_limiter.py +33 -0
  14. holmes/core/tools_utils/tool_executor.py +2 -2
  15. holmes/core/toolset_manager.py +150 -3
  16. holmes/core/tracing.py +6 -1
  17. holmes/core/transformers/__init__.py +23 -0
  18. holmes/core/transformers/base.py +62 -0
  19. holmes/core/transformers/llm_summarize.py +174 -0
  20. holmes/core/transformers/registry.py +122 -0
  21. holmes/core/transformers/transformer.py +31 -0
  22. holmes/main.py +5 -0
  23. holmes/plugins/toolsets/aks-node-health.yaml +46 -0
  24. holmes/plugins/toolsets/aks.yaml +64 -0
  25. holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +17 -15
  26. holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +8 -4
  27. holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +7 -3
  28. holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +3 -3
  29. holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +3 -3
  30. holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +7 -3
  31. holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +4 -4
  32. holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +7 -3
  33. holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +7 -3
  34. holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +7 -3
  35. holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +7 -3
  36. holmes/plugins/toolsets/bash/bash_toolset.py +6 -6
  37. holmes/plugins/toolsets/bash/common/bash.py +7 -7
  38. holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +5 -3
  39. holmes/plugins/toolsets/datadog/toolset_datadog_general.py +16 -17
  40. holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +9 -10
  41. holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +21 -22
  42. holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +8 -8
  43. holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +18 -19
  44. holmes/plugins/toolsets/git.py +22 -22
  45. holmes/plugins/toolsets/grafana/common.py +14 -2
  46. holmes/plugins/toolsets/grafana/grafana_tempo_api.py +473 -0
  47. holmes/plugins/toolsets/grafana/toolset_grafana.py +4 -4
  48. holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +3 -3
  49. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +246 -11
  50. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +662 -290
  51. holmes/plugins/toolsets/grafana/trace_parser.py +1 -1
  52. holmes/plugins/toolsets/internet/internet.py +3 -3
  53. holmes/plugins/toolsets/internet/notion.py +3 -3
  54. holmes/plugins/toolsets/investigator/core_investigation.py +3 -3
  55. holmes/plugins/toolsets/kafka.py +18 -18
  56. holmes/plugins/toolsets/kubernetes.yaml +58 -0
  57. holmes/plugins/toolsets/kubernetes_logs.py +6 -6
  58. holmes/plugins/toolsets/kubernetes_logs.yaml +32 -0
  59. holmes/plugins/toolsets/mcp/toolset_mcp.py +4 -4
  60. holmes/plugins/toolsets/newrelic.py +8 -8
  61. holmes/plugins/toolsets/opensearch/opensearch.py +5 -5
  62. holmes/plugins/toolsets/opensearch/opensearch_logs.py +7 -7
  63. holmes/plugins/toolsets/opensearch/opensearch_traces.py +10 -10
  64. holmes/plugins/toolsets/prometheus/prometheus.py +172 -39
  65. holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +25 -0
  66. holmes/plugins/toolsets/prometheus/utils.py +28 -0
  67. holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +6 -4
  68. holmes/plugins/toolsets/robusta/robusta.py +10 -10
  69. holmes/plugins/toolsets/runbook/runbook_fetcher.py +4 -4
  70. holmes/plugins/toolsets/servicenow/servicenow.py +6 -6
  71. holmes/plugins/toolsets/utils.py +88 -0
  72. holmes/utils/config_utils.py +91 -0
  73. holmes/utils/env.py +7 -0
  74. holmes/utils/holmes_status.py +2 -1
  75. holmes/utils/sentry_helper.py +41 -0
  76. holmes/utils/stream.py +9 -0
  77. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/METADATA +10 -14
  78. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/RECORD +81 -71
  79. holmes/plugins/toolsets/grafana/tempo_api.py +0 -124
  80. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/LICENSE.txt +0 -0
  81. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/WHEEL +0 -0
  82. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  import subprocess
2
- from holmes.core.tools import StructuredToolResult, ToolResultStatus
2
+ from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
3
3
 
4
4
 
5
5
  def execute_bash_command(cmd: str, timeout: int, params: dict) -> StructuredToolResult:
@@ -18,11 +18,11 @@ def execute_bash_command(cmd: str, timeout: int, params: dict) -> StructuredTool
18
18
  stdout = process.stdout.strip() if process.stdout else ""
19
19
  result_data = f"{cmd}\n" f"{stdout}"
20
20
 
21
- status = ToolResultStatus.ERROR
21
+ status = StructuredToolResultStatus.ERROR
22
22
  if process.returncode == 0 and stdout:
23
- status = ToolResultStatus.SUCCESS
23
+ status = StructuredToolResultStatus.SUCCESS
24
24
  elif not stdout:
25
- status = ToolResultStatus.NO_DATA
25
+ status = StructuredToolResultStatus.NO_DATA
26
26
 
27
27
  return StructuredToolResult(
28
28
  status=status,
@@ -33,20 +33,20 @@ def execute_bash_command(cmd: str, timeout: int, params: dict) -> StructuredTool
33
33
  )
34
34
  except subprocess.TimeoutExpired:
35
35
  return StructuredToolResult(
36
- status=ToolResultStatus.ERROR,
36
+ status=StructuredToolResultStatus.ERROR,
37
37
  error=f"Error: Command '{cmd}' timed out after {timeout} seconds.",
38
38
  params=params,
39
39
  )
40
40
  except FileNotFoundError:
41
41
  # This might occur if /bin/bash is not found, or if shell=False and command is not found
42
42
  return StructuredToolResult(
43
- status=ToolResultStatus.ERROR,
43
+ status=StructuredToolResultStatus.ERROR,
44
44
  error="Error: Bash executable or command not found. Ensure bash is installed and the command is valid.",
45
45
  params=params,
46
46
  )
47
47
  except Exception as e:
48
48
  return StructuredToolResult(
49
- status=ToolResultStatus.ERROR,
49
+ status=StructuredToolResultStatus.ERROR,
50
50
  error=f"Error executing command '{cmd}': {str(e)}",
51
51
  params=params,
52
52
  )
@@ -3,7 +3,7 @@ from typing import Any, Optional, Tuple, Set
3
3
  from holmes.core.tools import (
4
4
  CallablePrerequisite,
5
5
  StructuredToolResult,
6
- ToolResultStatus,
6
+ StructuredToolResultStatus,
7
7
  ToolsetTag,
8
8
  )
9
9
  from holmes.plugins.toolsets.consts import (
@@ -74,7 +74,7 @@ class CoralogixLogsToolset(BasePodLoggingToolset):
74
74
  def fetch_pod_logs(self, params: FetchPodLogsParams) -> StructuredToolResult:
75
75
  if not self.coralogix_config:
76
76
  return StructuredToolResult(
77
- status=ToolResultStatus.ERROR,
77
+ status=StructuredToolResultStatus.ERROR,
78
78
  error=f"The {self.name} toolset is not configured",
79
79
  params=params.model_dump(),
80
80
  )
@@ -102,7 +102,9 @@ class CoralogixLogsToolset(BasePodLoggingToolset):
102
102
 
103
103
  return StructuredToolResult(
104
104
  status=(
105
- ToolResultStatus.ERROR if logs_data.error else ToolResultStatus.SUCCESS
105
+ StructuredToolResultStatus.ERROR
106
+ if logs_data.error
107
+ else StructuredToolResultStatus.SUCCESS
106
108
  ),
107
109
  error=logs_data.error,
108
110
  data=data,
@@ -13,7 +13,7 @@ from holmes.core.tools import (
13
13
  ToolParameter,
14
14
  Toolset,
15
15
  StructuredToolResult,
16
- ToolResultStatus,
16
+ StructuredToolResultStatus,
17
17
  ToolsetTag,
18
18
  )
19
19
  from holmes.plugins.toolsets.consts import TOOLSET_CONFIG_MISSING_ERROR
@@ -170,7 +170,7 @@ class DatadogGeneralToolset(Toolset):
170
170
  super().__init__(
171
171
  name="datadog/general",
172
172
  description="General-purpose Datadog API access for read-only operations including monitors, dashboards, SLOs, incidents, synthetics, and more",
173
- docs_url="https://docs.datadoghq.com/api/latest/",
173
+ docs_url="https://holmesgpt.dev/data-sources/builtin-toolsets/datadog/",
174
174
  icon_url="https://imgix.datadoghq.com//img/about/presskit/DDlogo.jpg",
175
175
  prerequisites=[CallablePrerequisite(callable=self.prerequisites_callable)],
176
176
  tools=[
@@ -178,7 +178,6 @@ class DatadogGeneralToolset(Toolset):
178
178
  DatadogAPIPostSearch(toolset=self),
179
179
  ListDatadogAPIResources(toolset=self),
180
180
  ],
181
- experimental=True,
182
181
  tags=[ToolsetTag.CORE],
183
182
  )
184
183
  template_file_path = os.path.abspath(
@@ -334,7 +333,7 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
334
333
 
335
334
  if not self.toolset.dd_config:
336
335
  return StructuredToolResult(
337
- status=ToolResultStatus.ERROR,
336
+ status=StructuredToolResultStatus.ERROR,
338
337
  error=TOOLSET_CONFIG_MISSING_ERROR,
339
338
  params=params,
340
339
  )
@@ -351,7 +350,7 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
351
350
  if not is_allowed:
352
351
  logging.error(f"Endpoint validation failed: {error_msg}")
353
352
  return StructuredToolResult(
354
- status=ToolResultStatus.ERROR,
353
+ status=StructuredToolResultStatus.ERROR,
355
354
  error=f"Endpoint validation failed: {error_msg}",
356
355
  params=params,
357
356
  )
@@ -382,13 +381,13 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
382
381
  > self.toolset.dd_config.max_response_size
383
382
  ):
384
383
  return StructuredToolResult(
385
- status=ToolResultStatus.ERROR,
384
+ status=StructuredToolResultStatus.ERROR,
386
385
  error=f"Response too large (>{self.toolset.dd_config.max_response_size} bytes)",
387
386
  params=params,
388
387
  )
389
388
 
390
389
  return StructuredToolResult(
391
- status=ToolResultStatus.SUCCESS,
390
+ status=StructuredToolResultStatus.SUCCESS,
392
391
  data=response_str,
393
392
  params=params,
394
393
  )
@@ -408,7 +407,7 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
408
407
  error_msg = f"API error {e.status_code}: {str(e)}"
409
408
 
410
409
  return StructuredToolResult(
411
- status=ToolResultStatus.ERROR,
410
+ status=StructuredToolResultStatus.ERROR,
412
411
  error=error_msg,
413
412
  params=params,
414
413
  invocation=json.dumps({"url": url, "params": query_params})
@@ -419,7 +418,7 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
419
418
  except Exception as e:
420
419
  logging.exception(f"Failed to query Datadog API: {params}", exc_info=True)
421
420
  return StructuredToolResult(
422
- status=ToolResultStatus.ERROR,
421
+ status=StructuredToolResultStatus.ERROR,
423
422
  error=f"Unexpected error: {str(e)}",
424
423
  params=params,
425
424
  )
@@ -470,7 +469,7 @@ class DatadogAPIPostSearch(BaseDatadogGeneralTool):
470
469
 
471
470
  if not self.toolset.dd_config:
472
471
  return StructuredToolResult(
473
- status=ToolResultStatus.ERROR,
472
+ status=StructuredToolResultStatus.ERROR,
474
473
  error=TOOLSET_CONFIG_MISSING_ERROR,
475
474
  params=params,
476
475
  )
@@ -487,7 +486,7 @@ class DatadogAPIPostSearch(BaseDatadogGeneralTool):
487
486
  if not is_allowed:
488
487
  logging.error(f"Endpoint validation failed: {error_msg}")
489
488
  return StructuredToolResult(
490
- status=ToolResultStatus.ERROR,
489
+ status=StructuredToolResultStatus.ERROR,
491
490
  error=f"Endpoint validation failed: {error_msg}",
492
491
  params=params,
493
492
  )
@@ -518,13 +517,13 @@ class DatadogAPIPostSearch(BaseDatadogGeneralTool):
518
517
  > self.toolset.dd_config.max_response_size
519
518
  ):
520
519
  return StructuredToolResult(
521
- status=ToolResultStatus.ERROR,
520
+ status=StructuredToolResultStatus.ERROR,
522
521
  error=f"Response too large (>{self.toolset.dd_config.max_response_size} bytes)",
523
522
  params=params,
524
523
  )
525
524
 
526
525
  return StructuredToolResult(
527
- status=ToolResultStatus.SUCCESS,
526
+ status=StructuredToolResultStatus.SUCCESS,
528
527
  data=response_str,
529
528
  params=params,
530
529
  )
@@ -544,7 +543,7 @@ class DatadogAPIPostSearch(BaseDatadogGeneralTool):
544
543
  error_msg = f"API error {e.status_code}: {str(e)}"
545
544
 
546
545
  return StructuredToolResult(
547
- status=ToolResultStatus.ERROR,
546
+ status=StructuredToolResultStatus.ERROR,
548
547
  error=error_msg,
549
548
  params=params,
550
549
  invocation=json.dumps({"url": url, "body": body}) if url else None,
@@ -553,7 +552,7 @@ class DatadogAPIPostSearch(BaseDatadogGeneralTool):
553
552
  except Exception as e:
554
553
  logging.exception(f"Failed to query Datadog API: {params}", exc_info=True)
555
554
  return StructuredToolResult(
556
- status=ToolResultStatus.ERROR,
555
+ status=StructuredToolResultStatus.ERROR,
557
556
  error=f"Unexpected error: {str(e)}",
558
557
  params=params,
559
558
  )
@@ -692,7 +691,7 @@ class ListDatadogAPIResources(BaseDatadogGeneralTool):
692
691
  matching_categories = {k: v for k, v in resources.items() if category in k}
693
692
  if not matching_categories:
694
693
  return StructuredToolResult(
695
- status=ToolResultStatus.ERROR,
694
+ status=StructuredToolResultStatus.ERROR,
696
695
  error=f"Unknown category: {category}. Available: {', '.join(resources.keys())}",
697
696
  params=params,
698
697
  )
@@ -716,7 +715,7 @@ class ListDatadogAPIResources(BaseDatadogGeneralTool):
716
715
  output.append("Example: datadog_api_get with endpoint='/api/v1/monitors'")
717
716
 
718
717
  return StructuredToolResult(
719
- status=ToolResultStatus.SUCCESS,
718
+ status=StructuredToolResultStatus.SUCCESS,
720
719
  data="\n".join(output),
721
720
  params=params,
722
721
  )
@@ -8,7 +8,7 @@ from holmes.core.tools import (
8
8
  ToolsetTag,
9
9
  )
10
10
  from pydantic import BaseModel, Field
11
- from holmes.core.tools import StructuredToolResult, ToolResultStatus
11
+ from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
12
12
  from holmes.plugins.toolsets.consts import TOOLSET_CONFIG_MISSING_ERROR
13
13
  from holmes.plugins.toolsets.datadog.datadog_api import (
14
14
  DatadogBaseConfig,
@@ -151,11 +151,10 @@ class DatadogLogsToolset(BasePodLoggingToolset):
151
151
  super().__init__(
152
152
  name="datadog/logs",
153
153
  description="Toolset for fetching logs from Datadog, including historical data for pods no longer in the cluster",
154
- docs_url="https://docs.datadoghq.com/api/latest/logs/",
154
+ docs_url="https://holmesgpt.dev/data-sources/builtin-toolsets/datadog/",
155
155
  icon_url="https://imgix.datadoghq.com//img/about/presskit/DDlogo.jpg",
156
156
  prerequisites=[CallablePrerequisite(callable=self.prerequisites_callable)],
157
157
  tools=[], # Initialize with empty tools first
158
- experimental=True,
159
158
  tags=[ToolsetTag.CORE],
160
159
  )
161
160
  # Now that parent is initialized and self.name exists, create the tool
@@ -168,7 +167,7 @@ class DatadogLogsToolset(BasePodLoggingToolset):
168
167
  def fetch_pod_logs(self, params: FetchPodLogsParams) -> StructuredToolResult:
169
168
  if not self.dd_config:
170
169
  return StructuredToolResult(
171
- status=ToolResultStatus.ERROR,
170
+ status=StructuredToolResultStatus.ERROR,
172
171
  data=TOOLSET_CONFIG_MISSING_ERROR,
173
172
  params=params.model_dump(),
174
173
  )
@@ -183,13 +182,13 @@ class DatadogLogsToolset(BasePodLoggingToolset):
183
182
  if raw_logs:
184
183
  logs_str = format_logs(raw_logs)
185
184
  return StructuredToolResult(
186
- status=ToolResultStatus.SUCCESS,
185
+ status=StructuredToolResultStatus.SUCCESS,
187
186
  data=logs_str,
188
187
  params=params.model_dump(),
189
188
  )
190
189
 
191
190
  return StructuredToolResult(
192
- status=ToolResultStatus.NO_DATA,
191
+ status=StructuredToolResultStatus.NO_DATA,
193
192
  params=params.model_dump(),
194
193
  )
195
194
 
@@ -203,7 +202,7 @@ class DatadogLogsToolset(BasePodLoggingToolset):
203
202
  error_msg = f"Exception while querying Datadog: {str(e)}"
204
203
 
205
204
  return StructuredToolResult(
206
- status=ToolResultStatus.ERROR,
205
+ status=StructuredToolResultStatus.ERROR,
207
206
  error=error_msg,
208
207
  params=params.model_dump(),
209
208
  invocation=json.dumps(e.payload),
@@ -214,7 +213,7 @@ class DatadogLogsToolset(BasePodLoggingToolset):
214
213
  f"Failed to query Datadog logs for params: {params}", exc_info=True
215
214
  )
216
215
  return StructuredToolResult(
217
- status=ToolResultStatus.ERROR,
216
+ status=StructuredToolResultStatus.ERROR,
218
217
  error=f"Exception while querying Datadog: {str(e)}",
219
218
  params=params.model_dump(),
220
219
  )
@@ -235,11 +234,11 @@ class DatadogLogsToolset(BasePodLoggingToolset):
235
234
 
236
235
  result = self.fetch_pod_logs(healthcheck_params)
237
236
 
238
- if result.status == ToolResultStatus.ERROR:
237
+ if result.status == StructuredToolResultStatus.ERROR:
239
238
  error_msg = result.error or "Unknown error during healthcheck"
240
239
  logging.error(f"Datadog healthcheck failed: {error_msg}")
241
240
  return False, f"Datadog healthcheck failed: {error_msg}"
242
- elif result.status == ToolResultStatus.NO_DATA:
241
+ elif result.status == StructuredToolResultStatus.NO_DATA:
243
242
  error_msg = "No logs were found in the last 48 hours using wildcards for pod and namespace. Is the configuration correct?"
244
243
  logging.error(f"Datadog healthcheck failed: {error_msg}")
245
244
  return False, f"Datadog healthcheck failed: {error_msg}"
@@ -7,7 +7,7 @@ from holmes.core.tools import (
7
7
  StructuredToolResult,
8
8
  Tool,
9
9
  ToolParameter,
10
- ToolResultStatus,
10
+ StructuredToolResultStatus,
11
11
  Toolset,
12
12
  ToolsetTag,
13
13
  )
@@ -80,7 +80,7 @@ class ListActiveMetrics(BaseDatadogMetricsTool):
80
80
  ) -> StructuredToolResult:
81
81
  if not self.toolset.dd_config:
82
82
  return StructuredToolResult(
83
- status=ToolResultStatus.ERROR,
83
+ status=StructuredToolResultStatus.ERROR,
84
84
  error=TOOLSET_CONFIG_MISSING_ERROR,
85
85
  params=params,
86
86
  )
@@ -121,7 +121,7 @@ class ListActiveMetrics(BaseDatadogMetricsTool):
121
121
  metrics = data.get("metrics", [])
122
122
  if not metrics:
123
123
  return StructuredToolResult(
124
- status=ToolResultStatus.ERROR,
124
+ status=StructuredToolResultStatus.ERROR,
125
125
  data="Your filter returned no metrics. Change your filter and try again",
126
126
  params=params,
127
127
  )
@@ -133,7 +133,7 @@ class ListActiveMetrics(BaseDatadogMetricsTool):
133
133
  output.append(metric)
134
134
 
135
135
  return StructuredToolResult(
136
- status=ToolResultStatus.SUCCESS,
136
+ status=StructuredToolResultStatus.SUCCESS,
137
137
  data="\n".join(output),
138
138
  params=params,
139
139
  )
@@ -152,7 +152,7 @@ class ListActiveMetrics(BaseDatadogMetricsTool):
152
152
  error_msg = f"Exception while querying Datadog: {str(e)}"
153
153
 
154
154
  return StructuredToolResult(
155
- status=ToolResultStatus.ERROR,
155
+ status=StructuredToolResultStatus.ERROR,
156
156
  error=error_msg,
157
157
  params=params,
158
158
  invocation=json.dumps({"url": url, "params": query_params})
@@ -165,7 +165,7 @@ class ListActiveMetrics(BaseDatadogMetricsTool):
165
165
  f"Failed to query Datadog metrics for params: {params}", exc_info=True
166
166
  )
167
167
  return StructuredToolResult(
168
- status=ToolResultStatus.ERROR,
168
+ status=StructuredToolResultStatus.ERROR,
169
169
  error=f"Exception while querying Datadog: {str(e)}",
170
170
  params=params,
171
171
  )
@@ -222,7 +222,7 @@ class QueryMetrics(BaseDatadogMetricsTool):
222
222
  ) -> StructuredToolResult:
223
223
  if not self.toolset.dd_config:
224
224
  return StructuredToolResult(
225
- status=ToolResultStatus.ERROR,
225
+ status=StructuredToolResultStatus.ERROR,
226
226
  error=TOOLSET_CONFIG_MISSING_ERROR,
227
227
  params=params,
228
228
  )
@@ -262,7 +262,7 @@ class QueryMetrics(BaseDatadogMetricsTool):
262
262
 
263
263
  if not series:
264
264
  return StructuredToolResult(
265
- status=ToolResultStatus.NO_DATA,
265
+ status=StructuredToolResultStatus.NO_DATA,
266
266
  error="The query returned no data. Please check your query syntax and time range.",
267
267
  params=params,
268
268
  )
@@ -317,7 +317,7 @@ class QueryMetrics(BaseDatadogMetricsTool):
317
317
 
318
318
  data_str = json.dumps(response_data, indent=2)
319
319
  return StructuredToolResult(
320
- status=ToolResultStatus.SUCCESS,
320
+ status=StructuredToolResultStatus.SUCCESS,
321
321
  data=data_str,
322
322
  params=params,
323
323
  )
@@ -336,7 +336,7 @@ class QueryMetrics(BaseDatadogMetricsTool):
336
336
  error_msg = f"Exception while querying Datadog: {str(e)}"
337
337
 
338
338
  return StructuredToolResult(
339
- status=ToolResultStatus.ERROR,
339
+ status=StructuredToolResultStatus.ERROR,
340
340
  error=error_msg,
341
341
  params=params,
342
342
  invocation=json.dumps({"url": url, "params": query_params})
@@ -350,7 +350,7 @@ class QueryMetrics(BaseDatadogMetricsTool):
350
350
  )
351
351
 
352
352
  return StructuredToolResult(
353
- status=ToolResultStatus.ERROR,
353
+ status=StructuredToolResultStatus.ERROR,
354
354
  error=f"Exception while querying Datadog: {str(e)}",
355
355
  params=params,
356
356
  )
@@ -380,7 +380,7 @@ class QueryMetricsMetadata(BaseDatadogMetricsTool):
380
380
  ) -> StructuredToolResult:
381
381
  if not self.toolset.dd_config:
382
382
  return StructuredToolResult(
383
- status=ToolResultStatus.ERROR,
383
+ status=StructuredToolResultStatus.ERROR,
384
384
  error=TOOLSET_CONFIG_MISSING_ERROR,
385
385
  params=params,
386
386
  )
@@ -396,7 +396,7 @@ class QueryMetricsMetadata(BaseDatadogMetricsTool):
396
396
 
397
397
  if not metric_names:
398
398
  return StructuredToolResult(
399
- status=ToolResultStatus.ERROR,
399
+ status=StructuredToolResultStatus.ERROR,
400
400
  error="metric_names cannot be empty",
401
401
  params=params,
402
402
  )
@@ -442,14 +442,14 @@ class QueryMetricsMetadata(BaseDatadogMetricsTool):
442
442
 
443
443
  if not results and errors:
444
444
  return StructuredToolResult(
445
- status=ToolResultStatus.ERROR,
445
+ status=StructuredToolResultStatus.ERROR,
446
446
  error="Failed to retrieve metadata for all metrics",
447
447
  data=json.dumps(response_data, indent=2),
448
448
  params=params,
449
449
  )
450
450
 
451
451
  return StructuredToolResult(
452
- status=ToolResultStatus.SUCCESS,
452
+ status=StructuredToolResultStatus.SUCCESS,
453
453
  data=json.dumps(response_data, indent=2),
454
454
  params=params,
455
455
  )
@@ -461,7 +461,7 @@ class QueryMetricsMetadata(BaseDatadogMetricsTool):
461
461
  )
462
462
 
463
463
  return StructuredToolResult(
464
- status=ToolResultStatus.ERROR,
464
+ status=StructuredToolResultStatus.ERROR,
465
465
  error=f"Exception while querying Datadog: {str(e)}",
466
466
  params=params,
467
467
  )
@@ -496,7 +496,7 @@ class ListMetricTags(BaseDatadogMetricsTool):
496
496
  ) -> StructuredToolResult:
497
497
  if not self.toolset.dd_config:
498
498
  return StructuredToolResult(
499
- status=ToolResultStatus.ERROR,
499
+ status=StructuredToolResultStatus.ERROR,
500
500
  error=TOOLSET_CONFIG_MISSING_ERROR,
501
501
  params=params,
502
502
  )
@@ -519,7 +519,7 @@ class ListMetricTags(BaseDatadogMetricsTool):
519
519
  )
520
520
 
521
521
  return StructuredToolResult(
522
- status=ToolResultStatus.SUCCESS,
522
+ status=StructuredToolResultStatus.SUCCESS,
523
523
  data=data,
524
524
  params=params,
525
525
  )
@@ -540,7 +540,7 @@ class ListMetricTags(BaseDatadogMetricsTool):
540
540
  error_msg = f"Exception while querying Datadog: {str(e)}"
541
541
 
542
542
  return StructuredToolResult(
543
- status=ToolResultStatus.ERROR,
543
+ status=StructuredToolResultStatus.ERROR,
544
544
  error=error_msg,
545
545
  params=params,
546
546
  invocation=json.dumps({"url": url, "params": query_params})
@@ -554,7 +554,7 @@ class ListMetricTags(BaseDatadogMetricsTool):
554
554
  exc_info=True,
555
555
  )
556
556
  return StructuredToolResult(
557
- status=ToolResultStatus.ERROR,
557
+ status=StructuredToolResultStatus.ERROR,
558
558
  error=f"Exception while querying Datadog: {str(e)}",
559
559
  params=params,
560
560
  )
@@ -571,7 +571,7 @@ class DatadogMetricsToolset(Toolset):
571
571
  super().__init__(
572
572
  name="datadog/metrics",
573
573
  description="Toolset for fetching metrics and metadata from Datadog, including historical data for pods no longer in the cluster",
574
- docs_url="https://docs.datadoghq.com/api/latest/metrics/",
574
+ docs_url="https://holmesgpt.dev/data-sources/builtin-toolsets/datadog/",
575
575
  icon_url="https://imgix.datadoghq.com//img/about/presskit/DDlogo.jpg",
576
576
  prerequisites=[CallablePrerequisite(callable=self.prerequisites_callable)],
577
577
  tools=[
@@ -580,7 +580,6 @@ class DatadogMetricsToolset(Toolset):
580
580
  QueryMetricsMetadata(toolset=self),
581
581
  ListMetricTags(toolset=self),
582
582
  ],
583
- experimental=True,
584
583
  tags=[ToolsetTag.CORE],
585
584
  )
586
585
  self._reload_instructions()
@@ -10,7 +10,7 @@ from holmes.core.tools import (
10
10
  StructuredToolResult,
11
11
  Tool,
12
12
  ToolParameter,
13
- ToolResultStatus,
13
+ StructuredToolResultStatus,
14
14
  Toolset,
15
15
  ToolsetTag,
16
16
  )
@@ -97,7 +97,7 @@ class GenerateRDSPerformanceReport(BaseDatadogRDSTool):
97
97
  ) -> StructuredToolResult:
98
98
  if not self.toolset.dd_config:
99
99
  return StructuredToolResult(
100
- status=ToolResultStatus.ERROR,
100
+ status=StructuredToolResultStatus.ERROR,
101
101
  error=TOOLSET_CONFIG_MISSING_ERROR,
102
102
  params=params,
103
103
  )
@@ -150,7 +150,7 @@ class GenerateRDSPerformanceReport(BaseDatadogRDSTool):
150
150
  formatted_report = self._format_report(report)
151
151
 
152
152
  return StructuredToolResult(
153
- status=ToolResultStatus.SUCCESS,
153
+ status=StructuredToolResultStatus.SUCCESS,
154
154
  data=formatted_report,
155
155
  params=params,
156
156
  )
@@ -158,7 +158,7 @@ class GenerateRDSPerformanceReport(BaseDatadogRDSTool):
158
158
  except Exception as e:
159
159
  logging.error(f"Error generating RDS performance report: {str(e)}")
160
160
  return StructuredToolResult(
161
- status=ToolResultStatus.ERROR,
161
+ status=StructuredToolResultStatus.ERROR,
162
162
  error=f"Failed to generate RDS performance report: {str(e)}",
163
163
  params=params,
164
164
  )
@@ -397,7 +397,7 @@ class GetTopWorstPerformingRDSInstances(BaseDatadogRDSTool):
397
397
  ) -> StructuredToolResult:
398
398
  if not self.toolset.dd_config:
399
399
  return StructuredToolResult(
400
- status=ToolResultStatus.ERROR,
400
+ status=StructuredToolResultStatus.ERROR,
401
401
  error=TOOLSET_CONFIG_MISSING_ERROR,
402
402
  params=params,
403
403
  )
@@ -416,7 +416,7 @@ class GetTopWorstPerformingRDSInstances(BaseDatadogRDSTool):
416
416
 
417
417
  if not instances:
418
418
  return StructuredToolResult(
419
- status=ToolResultStatus.NO_DATA,
419
+ status=StructuredToolResultStatus.NO_DATA,
420
420
  data="No RDS instances found with metrics in the specified time range",
421
421
  params=params,
422
422
  )
@@ -443,7 +443,7 @@ class GetTopWorstPerformingRDSInstances(BaseDatadogRDSTool):
443
443
  report += f"\n\nInstances:\n{json.dumps(worst_performers, indent=2)}"
444
444
 
445
445
  return StructuredToolResult(
446
- status=ToolResultStatus.SUCCESS,
446
+ status=StructuredToolResultStatus.SUCCESS,
447
447
  data=report,
448
448
  params=params,
449
449
  )
@@ -451,7 +451,7 @@ class GetTopWorstPerformingRDSInstances(BaseDatadogRDSTool):
451
451
  except Exception as e:
452
452
  logging.error(f"Error getting top worst performing RDS instances: {str(e)}")
453
453
  return StructuredToolResult(
454
- status=ToolResultStatus.ERROR,
454
+ status=StructuredToolResultStatus.ERROR,
455
455
  error=f"Failed to get top worst performing RDS instances: {str(e)}",
456
456
  params=params,
457
457
  )