44
55Utility tools allow AI agents to search for relevant tools based on natural language queries
66and execute them dynamically without hardcoding tool names.
7+
8+ Prerequisites:
9+ - STACKONE_API_KEY environment variable set
10+ - STACKONE_ACCOUNT_ID environment variable set (comma-separated for multiple)
11+ - At least one linked account in StackOne (this example uses BambooHR)
12+
13+ This example is runnable with the following command:
14+ ```bash
15+ uv run examples/utility_tools_example.py
16+ ```
717"""
818
919import os
1525# Load environment variables
1626load_dotenv ()
1727
28+ # Read account IDs from environment — supports comma-separated values
29+ _account_ids = [aid .strip () for aid in os .getenv ("STACKONE_ACCOUNT_ID" , "" ).split ("," ) if aid .strip ()]
30+
1831
1932def example_utility_tools_basic ():
2033 """Basic example of using utility tools for tool discovery"""
@@ -24,21 +37,22 @@ def example_utility_tools_basic():
2437 toolset = StackOneToolSet ()
2538
2639 # Get all available tools using MCP-backed fetch_tools()
27- all_tools = toolset .fetch_tools (actions = ["bamboohr_*" ])
28- print (f"Total BambooHR tools available: { len (all_tools )} " )
40+ all_tools = toolset .fetch_tools (account_ids = _account_ids )
41+ print (f"Total tools available: { len (all_tools )} " )
42+
43+ if not all_tools :
44+ print ("No tools found. Check your linked accounts." )
45+ return
2946
3047 # Get utility tools for dynamic discovery
3148 utility_tools = all_tools .utility_tools ()
3249
33- # Get the filter tool to search for relevant tools
34- filter_tool = utility_tools .get_tool ("tool_search" )
35- if filter_tool :
36- # Search for employee management tools
37- result = filter_tool .call (query = "manage employees create update list" , limit = 5 , minScore = 0.0 )
50+ # Search for employee management tools
51+ result = utility_tools .search_tool .call (query = "manage employees create update list" , limit = 5 )
3852
39- print ("Found relevant tools:" )
40- for tool in result .get ("tools" , []):
41- print (f" - { tool ['name' ]} (score: { tool ['score' ]:.2f} ): { tool ['description' ]} " )
53+ print ("Found relevant tools:" )
54+ for tool in result .get ("tools" , []):
55+ print (f" - { tool ['name' ]} (score: { tool ['score' ]:.2f} ): { tool ['description' ]} " )
4256
4357 print ()
4458
@@ -51,31 +65,31 @@ def example_utility_tools_with_execution():
5165 toolset = StackOneToolSet ()
5266
5367 # Get all tools using MCP-backed fetch_tools()
54- all_tools = toolset .fetch_tools ()
68+ all_tools = toolset .fetch_tools (account_ids = _account_ids )
69+
70+ if not all_tools :
71+ print ("No tools found. Check your linked accounts." )
72+ return
73+
5574 utility_tools = all_tools .utility_tools ()
5675
5776 # Step 1: Search for relevant tools
58- filter_tool = utility_tools .get_tool ("tool_search" )
59- execute_tool = utility_tools .get_tool ("tool_execute" )
60-
61- if filter_tool and execute_tool :
62- # Find tools for listing employees
63- search_result = filter_tool .call (query = "list all employees" , limit = 1 )
64-
65- tools_found = search_result .get ("tools" , [])
66- if tools_found :
67- best_tool = tools_found [0 ]
68- print (f"Best matching tool: { best_tool ['name' ]} " )
69- print (f"Description: { best_tool ['description' ]} " )
70- print (f"Relevance score: { best_tool ['score' ]:.2f} " )
71-
72- # Step 2: Execute the found tool
73- try :
74- print (f"\n Executing { best_tool ['name' ]} ..." )
75- result = execute_tool .call (toolName = best_tool ["name" ], params = {"limit" : 5 })
76- print (f"Execution result: { result } " )
77- except Exception as e :
78- print (f"Execution failed (expected in example): { e } " )
77+ search_result = utility_tools .search_tool .call (query = "list all employees" , limit = 1 )
78+
79+ tools_found = search_result .get ("tools" , [])
80+ if tools_found :
81+ best_tool = tools_found [0 ]
82+ print (f"Best matching tool: { best_tool ['name' ]} " )
83+ print (f"Description: { best_tool ['description' ]} " )
84+ print (f"Relevance score: { best_tool ['score' ]:.2f} " )
85+
86+ # Step 2: Execute the found tool
87+ try :
88+ print (f"\n Executing { best_tool ['name' ]} ..." )
89+ result = utility_tools .execute_tool .call (toolName = best_tool ["name" ], params = {"limit" : 5 })
90+ print (f"Execution result: { result } " )
91+ except Exception as e :
92+ print (f"Execution failed (expected in example): { e } " )
7993
8094 print ()
8195
@@ -94,7 +108,7 @@ def example_with_openai():
94108 toolset = StackOneToolSet ()
95109
96110 # Get BambooHR tools and their utility tools using MCP-backed fetch_tools()
97- bamboohr_tools = toolset .fetch_tools (actions = ["bamboohr_*" ])
111+ bamboohr_tools = toolset .fetch_tools (account_ids = _account_ids , actions = ["bamboohr_*" ])
98112 utility_tools = bamboohr_tools .utility_tools ()
99113
100114 # Convert to OpenAI format
@@ -142,7 +156,7 @@ def example_with_langchain():
142156 toolset = StackOneToolSet ()
143157
144158 # Get tools and convert to LangChain format using MCP-backed fetch_tools()
145- tools = toolset .fetch_tools (actions = ["bamboohr_list_*" ])
159+ tools = toolset .fetch_tools (account_ids = _account_ids , actions = ["bamboohr_list_*" ])
146160 langchain_tools = tools .to_langchain ()
147161
148162 # Get utility tools as well
@@ -194,6 +208,15 @@ def main():
194208 print ("=" * 60 )
195209 print ()
196210
211+ if not os .getenv ("STACKONE_API_KEY" ):
212+ print ("Set STACKONE_API_KEY to run these examples." )
213+ return
214+
215+ if not _account_ids :
216+ print ("Set STACKONE_ACCOUNT_ID to run these examples." )
217+ print ("(Comma-separated for multiple accounts)" )
218+ return
219+
197220 # Basic examples that work without external APIs
198221 example_utility_tools_basic ()
199222 example_utility_tools_with_execution ()
0 commit comments