holmesgpt 0.13.2__py3-none-any.whl → 0.16.2a0__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.
Files changed (134) hide show
  1. holmes/__init__.py +1 -1
  2. holmes/clients/robusta_client.py +17 -4
  3. holmes/common/env_vars.py +40 -1
  4. holmes/config.py +114 -144
  5. holmes/core/conversations.py +53 -14
  6. holmes/core/feedback.py +191 -0
  7. holmes/core/investigation.py +18 -22
  8. holmes/core/llm.py +489 -88
  9. holmes/core/models.py +103 -1
  10. holmes/core/openai_formatting.py +13 -0
  11. holmes/core/prompt.py +1 -1
  12. holmes/core/safeguards.py +4 -4
  13. holmes/core/supabase_dal.py +293 -100
  14. holmes/core/tool_calling_llm.py +423 -323
  15. holmes/core/tools.py +311 -33
  16. holmes/core/tools_utils/token_counting.py +14 -0
  17. holmes/core/tools_utils/tool_context_window_limiter.py +57 -0
  18. holmes/core/tools_utils/tool_executor.py +13 -8
  19. holmes/core/toolset_manager.py +155 -4
  20. holmes/core/tracing.py +6 -1
  21. holmes/core/transformers/__init__.py +23 -0
  22. holmes/core/transformers/base.py +62 -0
  23. holmes/core/transformers/llm_summarize.py +174 -0
  24. holmes/core/transformers/registry.py +122 -0
  25. holmes/core/transformers/transformer.py +31 -0
  26. holmes/core/truncation/compaction.py +59 -0
  27. holmes/core/truncation/dal_truncation_utils.py +23 -0
  28. holmes/core/truncation/input_context_window_limiter.py +218 -0
  29. holmes/interactive.py +177 -24
  30. holmes/main.py +7 -4
  31. holmes/plugins/prompts/_fetch_logs.jinja2 +26 -1
  32. holmes/plugins/prompts/_general_instructions.jinja2 +1 -2
  33. holmes/plugins/prompts/_runbook_instructions.jinja2 +23 -12
  34. holmes/plugins/prompts/conversation_history_compaction.jinja2 +88 -0
  35. holmes/plugins/prompts/generic_ask.jinja2 +2 -4
  36. holmes/plugins/prompts/generic_ask_conversation.jinja2 +2 -1
  37. holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +2 -1
  38. holmes/plugins/prompts/generic_investigation.jinja2 +2 -1
  39. holmes/plugins/prompts/investigation_procedure.jinja2 +48 -0
  40. holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +2 -1
  41. holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +2 -1
  42. holmes/plugins/runbooks/__init__.py +117 -18
  43. holmes/plugins/runbooks/catalog.json +2 -0
  44. holmes/plugins/toolsets/__init__.py +21 -8
  45. holmes/plugins/toolsets/aks-node-health.yaml +46 -0
  46. holmes/plugins/toolsets/aks.yaml +64 -0
  47. holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +26 -36
  48. holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +0 -1
  49. holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +10 -7
  50. holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +9 -6
  51. holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +8 -6
  52. holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +8 -6
  53. holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +9 -6
  54. holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +9 -7
  55. holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +9 -6
  56. holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +9 -6
  57. holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +9 -6
  58. holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +9 -6
  59. holmes/plugins/toolsets/bash/bash_toolset.py +10 -13
  60. holmes/plugins/toolsets/bash/common/bash.py +7 -7
  61. holmes/plugins/toolsets/cilium.yaml +284 -0
  62. holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +5 -3
  63. holmes/plugins/toolsets/datadog/datadog_api.py +490 -24
  64. holmes/plugins/toolsets/datadog/datadog_logs_instructions.jinja2 +21 -10
  65. holmes/plugins/toolsets/datadog/toolset_datadog_general.py +349 -216
  66. holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +190 -19
  67. holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +101 -44
  68. holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +13 -16
  69. holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +25 -31
  70. holmes/plugins/toolsets/git.py +51 -46
  71. holmes/plugins/toolsets/grafana/common.py +15 -3
  72. holmes/plugins/toolsets/grafana/grafana_api.py +46 -24
  73. holmes/plugins/toolsets/grafana/grafana_tempo_api.py +454 -0
  74. holmes/plugins/toolsets/grafana/loki/instructions.jinja2 +9 -0
  75. holmes/plugins/toolsets/grafana/loki/toolset_grafana_loki.py +117 -0
  76. holmes/plugins/toolsets/grafana/toolset_grafana.py +211 -91
  77. holmes/plugins/toolsets/grafana/toolset_grafana_dashboard.jinja2 +27 -0
  78. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +246 -11
  79. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +653 -293
  80. holmes/plugins/toolsets/grafana/trace_parser.py +1 -1
  81. holmes/plugins/toolsets/internet/internet.py +6 -7
  82. holmes/plugins/toolsets/internet/notion.py +5 -6
  83. holmes/plugins/toolsets/investigator/core_investigation.py +42 -34
  84. holmes/plugins/toolsets/kafka.py +25 -36
  85. holmes/plugins/toolsets/kubernetes.yaml +58 -84
  86. holmes/plugins/toolsets/kubernetes_logs.py +6 -6
  87. holmes/plugins/toolsets/kubernetes_logs.yaml +32 -0
  88. holmes/plugins/toolsets/logging_utils/logging_api.py +80 -4
  89. holmes/plugins/toolsets/mcp/toolset_mcp.py +181 -55
  90. holmes/plugins/toolsets/newrelic/__init__.py +0 -0
  91. holmes/plugins/toolsets/newrelic/new_relic_api.py +125 -0
  92. holmes/plugins/toolsets/newrelic/newrelic.jinja2 +41 -0
  93. holmes/plugins/toolsets/newrelic/newrelic.py +163 -0
  94. holmes/plugins/toolsets/opensearch/opensearch.py +10 -17
  95. holmes/plugins/toolsets/opensearch/opensearch_logs.py +7 -7
  96. holmes/plugins/toolsets/opensearch/opensearch_ppl_query_docs.jinja2 +1616 -0
  97. holmes/plugins/toolsets/opensearch/opensearch_query_assist.py +78 -0
  98. holmes/plugins/toolsets/opensearch/opensearch_query_assist_instructions.jinja2 +223 -0
  99. holmes/plugins/toolsets/opensearch/opensearch_traces.py +13 -16
  100. holmes/plugins/toolsets/openshift.yaml +283 -0
  101. holmes/plugins/toolsets/prometheus/prometheus.py +915 -390
  102. holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +43 -2
  103. holmes/plugins/toolsets/prometheus/utils.py +28 -0
  104. holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +9 -10
  105. holmes/plugins/toolsets/robusta/robusta.py +236 -65
  106. holmes/plugins/toolsets/robusta/robusta_instructions.jinja2 +26 -9
  107. holmes/plugins/toolsets/runbook/runbook_fetcher.py +137 -26
  108. holmes/plugins/toolsets/service_discovery.py +1 -1
  109. holmes/plugins/toolsets/servicenow_tables/instructions.jinja2 +83 -0
  110. holmes/plugins/toolsets/servicenow_tables/servicenow_tables.py +426 -0
  111. holmes/plugins/toolsets/utils.py +88 -0
  112. holmes/utils/config_utils.py +91 -0
  113. holmes/utils/default_toolset_installation_guide.jinja2 +1 -22
  114. holmes/utils/env.py +7 -0
  115. holmes/utils/global_instructions.py +75 -10
  116. holmes/utils/holmes_status.py +2 -1
  117. holmes/utils/holmes_sync_toolsets.py +0 -2
  118. holmes/utils/krr_utils.py +188 -0
  119. holmes/utils/sentry_helper.py +41 -0
  120. holmes/utils/stream.py +61 -7
  121. holmes/version.py +34 -14
  122. holmesgpt-0.16.2a0.dist-info/LICENSE +178 -0
  123. {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/METADATA +29 -27
  124. {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/RECORD +126 -102
  125. holmes/core/performance_timing.py +0 -72
  126. holmes/plugins/toolsets/grafana/tempo_api.py +0 -124
  127. holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +0 -110
  128. holmes/plugins/toolsets/newrelic.py +0 -231
  129. holmes/plugins/toolsets/servicenow/install.md +0 -37
  130. holmes/plugins/toolsets/servicenow/instructions.jinja2 +0 -3
  131. holmes/plugins/toolsets/servicenow/servicenow.py +0 -219
  132. holmesgpt-0.13.2.dist-info/LICENSE.txt +0 -21
  133. {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/WHEEL +0 -0
  134. {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/entry_points.txt +0 -0
@@ -1,63 +1,170 @@
1
1
  import logging
2
+ import os
2
3
  import textwrap
3
4
  from typing import Any, Dict, List, Optional
4
-
5
+ from holmes.core.supabase_dal import SupabaseDal
5
6
  from holmes.core.tools import (
6
7
  StructuredToolResult,
7
8
  Tool,
9
+ ToolInvokeContext,
8
10
  ToolParameter,
9
- ToolResultStatus,
11
+ StructuredToolResultStatus,
10
12
  Toolset,
11
13
  ToolsetTag,
12
14
  )
13
15
 
14
- from holmes.plugins.runbooks import get_runbook_by_path, DEFAULT_RUNBOOK_SEARCH_PATH
16
+ from holmes.plugins.runbooks import (
17
+ get_runbook_by_path,
18
+ load_runbook_catalog,
19
+ DEFAULT_RUNBOOK_SEARCH_PATH,
20
+ )
15
21
  from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
16
22
 
17
23
 
18
- # TODO(mainred): currently we support fetch runbooks hosted internally, in the future we may want to support fetching
19
- # runbooks from external sources as well.
20
24
  class RunbookFetcher(Tool):
21
25
  toolset: "RunbookToolset"
26
+ available_runbooks: List[str] = []
27
+ additional_search_paths: Optional[List[str]] = None
28
+ _dal: Optional[SupabaseDal] = None
29
+
30
+ def __init__(
31
+ self,
32
+ toolset: "RunbookToolset",
33
+ additional_search_paths: Optional[List[str]] = None,
34
+ dal: Optional[SupabaseDal] = None,
35
+ ):
36
+ catalog = load_runbook_catalog(dal=dal)
37
+ available_runbooks = []
38
+ if catalog:
39
+ available_runbooks = catalog.list_available_runbooks()
40
+
41
+ if additional_search_paths:
42
+ for search_path in additional_search_paths:
43
+ if not os.path.isdir(search_path):
44
+ continue
45
+
46
+ for file in os.listdir(search_path):
47
+ if file.endswith(".md") and file not in available_runbooks:
48
+ available_runbooks.append(f"{file}")
49
+
50
+ runbook_list = ", ".join([f'"{rb}"' for rb in available_runbooks])
22
51
 
23
- def __init__(self, toolset: "RunbookToolset"):
24
52
  super().__init__(
25
53
  name="fetch_runbook",
26
54
  description="Get runbook content by runbook link. Use this to get troubleshooting steps for incidents",
27
55
  parameters={
28
- # use link as a more generic term for runbook path, considering we may have external links in the future
29
- "link": ToolParameter(
30
- description="The link to the runbook",
56
+ "runbook_id": ToolParameter(
57
+ description=f"The runbook_id: either a UUID or a .md filename. Must be one of: {runbook_list}",
31
58
  type="string",
32
59
  required=True,
33
60
  ),
34
61
  },
35
- toolset=toolset, # type: ignore
62
+ toolset=toolset, # type: ignore[call-arg]
63
+ available_runbooks=available_runbooks, # type: ignore[call-arg]
64
+ additional_search_paths=additional_search_paths, # type: ignore[call-arg]
36
65
  )
66
+ self._dal = dal
67
+
68
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
69
+ runbook_id: str = params.get("runbook_id", "")
70
+ is_md_file: bool = True if runbook_id.endswith(".md") else False
71
+
72
+ # Validate link is not empty
73
+ if not runbook_id or not runbook_id.strip():
74
+ err_msg = (
75
+ "Runbook link cannot be empty. Please provide a valid runbook path."
76
+ )
77
+ logging.error(err_msg)
78
+ return StructuredToolResult(
79
+ status=StructuredToolResultStatus.ERROR,
80
+ error=err_msg,
81
+ params=params,
82
+ )
37
83
 
38
- def _invoke(
39
- self, params: dict, user_approved: bool = False
40
- ) -> StructuredToolResult:
41
- link: str = params["link"]
84
+ if is_md_file:
85
+ return self._get_md_runbook(runbook_id, params)
86
+ else:
87
+ return self._get_robusta_runbook(runbook_id, params)
88
+
89
+ def _get_robusta_runbook(self, link: str, params: dict) -> StructuredToolResult:
90
+ if self._dal and self._dal.enabled:
91
+ try:
92
+ runbook_content = self._dal.get_runbook_content(link)
93
+ if runbook_content:
94
+ return StructuredToolResult(
95
+ status=StructuredToolResultStatus.SUCCESS,
96
+ data=runbook_content.pretty(),
97
+ params=params,
98
+ )
99
+ else:
100
+ err_msg = f"Runbook with UUID '{link}' not found in remote storage."
101
+ logging.error(err_msg)
102
+ return StructuredToolResult(
103
+ status=StructuredToolResultStatus.ERROR,
104
+ error=err_msg,
105
+ params=params,
106
+ )
107
+ except Exception as e:
108
+ err_msg = f"Failed to fetch runbook with UUID '{link}': {str(e)}"
109
+ logging.error(err_msg)
110
+ return StructuredToolResult(
111
+ status=StructuredToolResultStatus.ERROR,
112
+ error=err_msg,
113
+ params=params,
114
+ )
115
+ else:
116
+ err_msg = "Runbook link appears to be a UUID, but no remote data access layer (dal) is enabled."
117
+ logging.error(err_msg)
118
+ return StructuredToolResult(
119
+ status=StructuredToolResultStatus.ERROR,
120
+ error=err_msg,
121
+ params=params,
122
+ )
42
123
 
124
+ def _get_md_runbook(self, link: str, params: dict) -> StructuredToolResult:
43
125
  search_paths = [DEFAULT_RUNBOOK_SEARCH_PATH]
44
- if self.toolset.config and "additional_search_paths" in self.toolset.config:
45
- search_paths.extend(self.toolset.config["additional_search_paths"])
126
+ if self.additional_search_paths:
127
+ search_paths.extend(self.additional_search_paths)
128
+ # Validate link is in the available runbooks list OR is a valid path within allowed directories
129
+ if link not in self.available_runbooks:
130
+ # Check if the link would resolve to a valid path within allowed directories
131
+ # This prevents path traversal attacks like ../../secret.md
132
+ is_valid_path = False
133
+ for search_path in search_paths:
134
+ candidate_path = os.path.join(search_path, link)
135
+ # Canonicalize both paths to resolve any .. or . components
136
+ real_search_path = os.path.realpath(search_path)
137
+ real_candidate_path = os.path.realpath(candidate_path)
138
+
139
+ # Check if the resolved path is within the allowed directory
140
+ if (
141
+ real_candidate_path.startswith(real_search_path + os.sep)
142
+ or real_candidate_path == real_search_path
143
+ ):
144
+ if os.path.isfile(real_candidate_path):
145
+ is_valid_path = True
146
+ break
147
+
148
+ if not is_valid_path:
149
+ err_msg = f"Invalid runbook link '{link}'. Must be one of: {', '.join(self.available_runbooks) if self.available_runbooks else 'No runbooks available'}"
150
+ logging.error(err_msg)
151
+ return StructuredToolResult(
152
+ status=StructuredToolResultStatus.ERROR,
153
+ error=err_msg,
154
+ params=params,
155
+ )
46
156
 
47
157
  runbook_path = get_runbook_by_path(link, search_paths)
48
-
49
158
  if runbook_path is None:
50
159
  err_msg = (
51
160
  f"Runbook '{link}' not found in any of the search paths: {search_paths}"
52
161
  )
53
162
  logging.error(err_msg)
54
163
  return StructuredToolResult(
55
- status=ToolResultStatus.ERROR,
164
+ status=StructuredToolResultStatus.ERROR,
56
165
  error=err_msg,
57
166
  params=params,
58
167
  )
59
-
60
- # Read and return the runbook content
61
168
  try:
62
169
  with open(runbook_path, "r") as file:
63
170
  content = file.read()
@@ -96,7 +203,7 @@ class RunbookFetcher(Tool):
96
203
  </example>
97
204
  """)
98
205
  return StructuredToolResult(
99
- status=ToolResultStatus.SUCCESS,
206
+ status=StructuredToolResultStatus.SUCCESS,
100
207
  data=wrapped_content,
101
208
  params=params,
102
209
  )
@@ -104,19 +211,23 @@ class RunbookFetcher(Tool):
104
211
  err_msg = f"Failed to read runbook {runbook_path}: {str(e)}"
105
212
  logging.error(err_msg)
106
213
  return StructuredToolResult(
107
- status=ToolResultStatus.ERROR,
214
+ status=StructuredToolResultStatus.ERROR,
108
215
  error=err_msg,
109
216
  params=params,
110
217
  )
111
218
 
112
219
  def get_parameterized_one_liner(self, params) -> str:
113
- path: str = params.get("link", "")
220
+ path: str = params.get("runbook_id", "")
114
221
  return f"{toolset_name_for_one_liner(self.toolset.name)}: Fetch Runbook {path}"
115
222
 
116
223
 
117
224
  class RunbookToolset(Toolset):
118
- def __init__(self, additional_search_paths: Optional[List[str]] = None):
119
- # Store additional search paths in config
225
+ def __init__(
226
+ self,
227
+ dal: Optional[SupabaseDal],
228
+ additional_search_paths: Optional[List[str]] = None,
229
+ ):
230
+ # Store additional search paths in config for RunbookFetcher to access
120
231
  config = {}
121
232
  if additional_search_paths:
122
233
  config["additional_search_paths"] = additional_search_paths
@@ -126,7 +237,7 @@ class RunbookToolset(Toolset):
126
237
  description="Fetch runbooks",
127
238
  icon_url="https://platform.robusta.dev/demos/runbook.svg",
128
239
  tools=[
129
- RunbookFetcher(self),
240
+ RunbookFetcher(self, additional_search_paths, dal),
130
241
  ],
131
242
  docs_url="https://holmesgpt.dev/data-sources/",
132
243
  tags=[
@@ -36,7 +36,7 @@ def find_service_url(label_selector):
36
36
  port = svc.spec.ports[0].port
37
37
  url = f"http://{name}.{namespace}.svc.{CLUSTER_DOMAIN}:{port}"
38
38
  logging.info(
39
- f"discovered service with label-selector: `{label_selector}` at url: `{url}`"
39
+ f"Discovered service with label-selector: `{label_selector}` at url: `{url}`"
40
40
  )
41
41
  return url
42
42
  except Exception:
@@ -0,0 +1,83 @@
1
+ ## ServiceNow Tables Toolset
2
+
3
+ This toolset provides access to ServiceNow tables for retrieving records and data.
4
+
5
+ ### Available Tools
6
+
7
+ 1. **servicenow_get_records**: Retrieve multiple records from a ServiceNow table with filtering capabilities
8
+ 2. **servicenow_get_record**: Retrieve a single record by its sys_id
9
+
10
+ **IMPORTANT**: For servicenow_get_record, you MUST have a valid sys_id value that was either:
11
+ - Provided by the user
12
+ - Obtained from a previous servicenow_get_records call
13
+ - Never guess or make up sys_id values - they are unique identifiers that must come from a legitimate source
14
+
15
+ ### Query Syntax
16
+
17
+ The `sysparm_query` parameter supports a powerful query language:
18
+ - Use `^` for AND conditions
19
+ - Use `^OR` for OR conditions
20
+ - Common operators:
21
+ - `=` (equals) - Use for exact matches, REQUIRED for reference fields
22
+ - `!=` (not equals)
23
+ - `LIKE` (contains) - Use for partial string matches on text fields only
24
+ - `STARTSWITH`
25
+ - `ENDSWITH`
26
+ - `CONTAINS`
27
+ - `ISNOTEMPTY`
28
+ - `ISEMPTY`
29
+ - `<`, `<=`, `>`, `>=` (comparisons)
30
+ - `BETWEEN` (for date ranges)
31
+
32
+ Example: `active=true^priority=1^short_descriptionLIKEerror`
33
+
34
+ **CRITICAL**: Reference fields (fields that link to other records) MUST use the `=` operator with the exact sys_id value. Never use `LIKE` with reference fields.
35
+ - ✅ Correct: `cmdb_ci=b0ccabf1c0a80009001f14fd151d8df0`
36
+ - ❌ Wrong: `cmdb_ciLIKE827b692d0ad337021abb72d3737ff401`
37
+
38
+ **Date Queries - Best Practice**:
39
+ Use `>=` and `<=` operators for date ranges. When using date-only format (YYYY-MM-DD), ServiceNow includes the entire day.
40
+ - ✅ Recommended: `sys_created_on>=2024-01-01^sys_created_on<=2024-01-31` (includes all of Jan 31)
41
+ - With time: `sys_created_on>=2024-01-01 00:00:00^sys_created_on<=2024-01-31 23:59:59`
42
+ - Avoid BETWEEN operator as date handling can be inconsistent
43
+
44
+ ### Understanding Field Types
45
+
46
+ In ServiceNow, fields can be of different types:
47
+ - **Text fields**: Store plain text (use LIKE, CONTAINS, STARTSWITH for partial matches)
48
+ - **Reference fields**: Store links to other records via sys_id (MUST use = for exact match)
49
+ - **Boolean fields**: Store true/false values
50
+ - **Date/Time fields**: Store timestamps (use comparison operators)
51
+
52
+ How to identify reference fields:
53
+ - When `sysparm_display_value=all`, reference fields return an object with {display_value, link, value}
54
+ - The 'value' property contains the sys_id
55
+ - Common reference fields: cmdb_ci, assigned_to, caller_id, company, location
56
+
57
+ ### Useful Tables
58
+
59
+ - **cmdb_ci** - Configuration items (applications, servers, infrastructure). Search by name to get sys_id.
60
+ - **change_request** - Links to CIs via cmdb_ci field. Use CI's sys_id to find who requested changes, when, and completion status.
61
+
62
+ {# Additional tables can be added by user #}
63
+
64
+ ### Discovering Tables
65
+
66
+ To discover available tables in ServiceNow, you can query the system table catalog:
67
+
68
+ ```
69
+ table_name: sys_db_object
70
+ sysparm_fields: name,label,description
71
+ sysparm_query: nameSTARTSWITHincident
72
+ ```
73
+
74
+ This will return tables with names starting with "incident". You can modify the query to search for other table patterns.
75
+
76
+ **Note**: ServiceNow contains many tables, so it's recommended to filter your search using `STARTSWITH`, `CONTAINS`, or `LIKE` operators to find relevant tables efficiently.
77
+
78
+ ### Tips for Usage
79
+
80
+ 1. Use `sysparm_view=mobile` to get a concise set of fields when exploring data
81
+ 2. Use `sysparm_fields` to specify exactly which fields you need to reduce response size
82
+ 3. The default limit is 100 records; increase it if you need more data
83
+ 4. Display values are returned by default (human-readable format)