Skip to main content

Quick Start

The most common pattern: create a toolset and give your agent search and execute tools. The agent discovers and runs tools on demand.
from stackone_ai import StackOneToolSet

# search_and_execute returns the tool_search + tool_execute meta tools, so search
# must be enabled on the toolset (pass search={} for defaults).
toolset = StackOneToolSet(search={"method": "auto"})

# Your agent gets 2 tools: tool_search + tool_execute
tools = toolset.openai(mode="search_and_execute", account_ids=["your-account-id"])
Pass tools to any OpenAI-compatible model and the agent will search for relevant tools, then execute them automatically. See the OpenAI integration guide for a full agent loop.

Fetch Tools

When you need specific tools instead of search and execute:
tools = toolset.fetch_tools(account_ids=["your-account-id"])
openai_tools = tools.to_openai()
# Filter by providers
tools = toolset.fetch_tools(
    providers=["hibob", "workday"],
    account_ids=["your-account-id"],
)

# Filter by actions with exact match
tools = toolset.fetch_tools(
    actions=["hibob_list_employees", "hibob_create_employees"],
    account_ids=["your-account-id"],
)

# Filter by actions with glob patterns
tools = toolset.fetch_tools(
    actions=["*_list_*"],
    account_ids=["your-account-id"],
)

# Combine multiple filters
tools = toolset.fetch_tools(
    providers=["hibob"],
    actions=["*_list_*"],
    account_ids=["your-account-id"],
)
See Tool Filtering for the full reference.
# Set accounts on the toolset for all subsequent calls
toolset.set_accounts(["account-123", "account-456"])
tools = toolset.fetch_tools()

# Or pass account IDs per request
tools = toolset.fetch_tools(account_ids=["account-123", "account-456"])

# Loop over customer accounts dynamically
customer_accounts = ["account-1", "account-2", "account-3"]

for account_id in customer_accounts:
    tools = toolset.fetch_tools(
        actions=["workday_list_workers"],
        account_ids=[account_id],
    )
    employee_tool = tools.get_tool("workday_list_workers")
    if employee_tool:
        employees = employee_tool.call()
        print(f"Found {len(employees['data'])} employees")

Tool Execution

Direct execution is useful for testing and debugging. In production, your agent framework handles tool calls automatically.
tools = toolset.fetch_tools(account_ids=["your-account-id"])
employee_tool = tools.get_tool("workday_list_workers")

# call() with keyword arguments
result = employee_tool.call(id="employee-123", include_details=True)
print(result["data"])

# execute() with dictionary payloads
result = employee_tool.execute({"id": "employee-123", "include_details": True})

# execute() with OpenAI-style arguments
payload = {"arguments": {"id": "employee-123"}}
result = employee_tool.execute(payload)
from stackone_ai.models import StackOneError, StackOneAPIError

try:
    result = employee_tool.call(id="employee-123")
    print("Success:", result)
except StackOneAPIError as e:
    print(f"API error: {e.message}")
except StackOneError as e:
    print(f"StackOne error: {e.message}")
except Exception as e:
    print(f"Unexpected error: {e}")
Actions that download a file (for example googledrive_unified_download_file, documents_download_file, or any *_unified_download_file) return raw bytes plus metadata, not parsed JSON. The SDK decides from the response Content-Type: JSON is parsed as usual, and anything else is treated as a file download. call() and execute() both return this dict directly (it isn’t wrapped in a result object), so read its values with dict keys like result["content"].
tools = toolset.fetch_tools(actions=["googledrive_*"], account_ids=["your-account-id"])
download = tools.get_tool("googledrive_unified_download_file")

result = download.execute({"id": "file-id"})

# result describes the file. Write the bytes straight to disk:
with open(result["file_name"] or "download.bin", "wb") as f:
    f.write(result["content"])
The returned dict, from both call() and execute():
KeyTypeDescription
contentbytesRaw file bytes. Not JSON-serializable (see note).
content_typestrFile MIME type (for example application/pdf), or application/octet-stream.
status_codeintHTTP status of the download response.
headersdictResponse headers.
file_namestr | NoneFilename from Content-Disposition (RFC 5987 filename* aware), else None.
content is raw bytes and is not JSON-serializable. If you forward tool results to an LLM (or anything that re-serializes to JSON), handle or strip the content key. For example, base64-encode it on the LLM-facing path.

Environment Configuration

export STACKONE_API_KEY=your_api_key
Account IDs are passed per-request when fetching tools or via toolset.openai(mode="search_and_execute", account_ids=[...]).

Next Steps