Skip to main content
New to tool search? Start with Tool Search 101 for an overview of why, how, and when to use it.
The simplest way to use tool search: give your agent tool_search and tool_execute, and let it discover tools on demand.
from stackone_ai import StackOneToolSet

toolset = StackOneToolSet()

# LLM receives only 2 tools: tool_search + tool_execute
openai_tools = toolset.openai(mode="search_and_execute")
Only 2 tools are sent to the LLM regardless of how many tools exist in your catalog. Token usage stays constant.

Framework Examples

import json
from openai import OpenAI
from stackone_ai import StackOneToolSet

toolset = StackOneToolSet()

# LLM receives only 2 tools: tool_search + tool_execute
openai_tools = toolset.openai(mode="search_and_execute", account_ids=["your-account-id"])

client = OpenAI()
messages = [
    {
        "role": "system",
        "content": (
            "Use tool_search to find relevant tools, then tool_execute to run them. "
            "Read parameter schemas from tool_search results carefully. "
            "If a tool needs a user URI, search for a 'get current user' tool first."
        ),
    },
    {"role": "user", "content": "List my upcoming Calendly events for the next week."},
]

for _step in range(10):
    response = client.chat.completions.create(
        model="gpt-5.4",
        messages=messages,
        tools=openai_tools,
        tool_choice="auto",
    )

    choice = response.choices[0]
    if not choice.message.tool_calls:
        print(choice.message.content)
        break

    messages.append(choice.message.model_dump(exclude_none=True))
    for tool_call in choice.message.tool_calls:
        result = toolset.execute(tool_call.function.name, tool_call.function.arguments)
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result),
        })
When you need to find tools yourself before passing them to an agent:
from stackone_ai import StackOneToolSet

toolset = StackOneToolSet()
tools = toolset.search_tools("manage employee records")

# Use with any framework
openai_tools = tools.to_openai()
langchain_tools = tools.to_langchain()
No configuration needed. Defaults to auto mode with sensible defaults.
ModeBehaviour
autoTries semantic API first, falls back to local search on failure. Recommended for production.
semanticStrict mode. Uses semantic API only, raises SemanticSearchError on failure.
localHybrid BM25 + TF-IDF search entirely in-process (powered by bm25s). No network call. Useful for offline or low-latency scenarios.
# Auto (default)
tools = toolset.search_tools("manage employees", search="auto")

# Semantic only
tools = toolset.search_tools("manage employees", search="semantic")

# Local only
tools = toolset.search_tools("manage employees", search="local")
Set default search options at the constructor level. These apply to all search calls unless overridden per-call.

SearchConfig Options

OptionTypeDescription
method"auto" | "semantic" | "local"Search mode (default: "auto")
top_kintMaximum number of tools to return
min_similarityfloatMinimum relevance score threshold (0-1)
from stackone_ai import StackOneToolSet

# Custom search config
toolset = StackOneToolSet(search={"method": "semantic", "top_k": 5})

# Disable search
toolset = StackOneToolSet(search=None)

# Default: search enabled with method="auto"
toolset = StackOneToolSet()
Per-call overrides take precedence over constructor defaults:
# Constructor sets top_k=5 for all search calls
toolset = StackOneToolSet(search={"method": "semantic", "top_k": 5})

# Uses constructor defaults: method="semantic", top_k=5
tools = toolset.search_tools("manage employees")

# top_k overridden to 10 for this call; method remains "semantic"
tools = toolset.search_tools("manage employees", top_k=10)
ParameterTypeDescription
querystrNatural language description of what you want to do
top_kint | NoneMaximum number of tools to return
search"auto" | "semantic" | "local"Search mode (default: "auto")
connectorstr | NoneFilter to a specific provider (e.g., "workday")
min_similarityfloat | NoneMinimum relevance score threshold (0-1)
account_idslist[str] | NoneOverride account IDs for this search

Advanced Patterns

Returns action IDs and similarity scores without fetching full tool definitions. Use it to inspect results before committing to a full fetch.
results = toolset.search_action_names("manage employees", top_k=5)

for r in results:
    print(f"{r.id}: {r.similarity_score:.2f}")
search_action_names() works with just STACKONE_API_KEY, no account ID needed. When called without account_ids, results come from the full StackOne catalog.
Returns a callable SearchTool for agent loops where the LLM decides what to search for.
search_tool = toolset.get_search_tool(search="auto")

# In an agent loop, call it with natural language queries
queries = [
    "create a new employee",
    "list job candidates",
    "send a message to a channel",
]

for query in queries:
    tools = search_tool(query, top_k=3)
    tool_names = [t.name for t in tools]
    print(f'"{query}" -> {", ".join(tool_names)}')

Next Steps