Skip to main content

Initialise the ToolSet

Start by creating a StackOneToolSet instance. The SDK automatically reads STACKONE_API_KEY, so you typically only provide fallback account IDs or custom HTTP settings:
from stackone_ai import StackOneToolSet

toolset = StackOneToolSet(
    search={"method": "auto", "top_k": 5},  # optional: configure default search behaviour
)
account_id = "your-customer-account-id"
The search parameter sets default search configuration for all search_tools() calls. Pass search=None to disable search, or omit it for the default (method="auto"). See Tool Search for details.

Fetch Tools

Use fetch_tools() to dynamically load tools from StackOne’s MCP endpoint with glob patterns:
# Get all BambooHR tools
bamboohr_tools = toolset.fetch_tools(actions=['bamboohr_*'], account_ids=[account_id])

# Get all HiBob tools
hibob_tools = toolset.fetch_tools(actions=['hibob_*'], account_ids=[account_id])

# Get specific list operations
list_tools = toolset.fetch_tools(actions=['*_list_*'], account_ids=[account_id])
fetch_tools() pulls tool definitions at runtime based on your account IDs, reusing the credentials you already configured (e.g., via STACKONE_API_KEY). This is useful for multi-tenant applications where each customer has different integrations connected.
You can filter tools by account IDs, providers, and action patterns:
# Filter by account IDs
toolset.set_accounts(["account-123", "account-456"])
tools = toolset.fetch_tools()
# OR
tools = toolset.fetch_tools(account_ids=["account-123", "account-456"])

# Filter by providers
tools = toolset.fetch_tools(providers=["hibob", "bamboohr"])

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

# Filter by actions with glob patterns
tools = toolset.fetch_tools(actions=["*_list_employees"])

# Combine multiple filters
tools = toolset.fetch_tools(
    account_ids=["account-123"],
    providers=["hibob"],
    actions=["*_list_*"],
)
This is useful when you want to:
  • Limit tools to specific linked accounts
  • Focus on specific providers
  • Get only certain types of operations (e.g., all “list” operations)
# Handle multiple customer accounts
customer_accounts = ['account-1', 'account-2', 'account-3']

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

Execute Tools

Basic Tool Execution

# Fetch tools for your account
tools = toolset.fetch_tools(actions=['bamboohr_*'], account_ids=[account_id])
employee_tool = tools.get_tool('bamboohr_list_employees')

# Execute with keyword arguments via call()
employees = employee_tool.call(limit=10, include_details=True)
print(employees.data)
# Method 1: call() with keyword arguments (recommended)
result = employee_tool.call(id="employee-123", include_details=True)

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

# Method 3: execute() with OpenAI-style arguments
payload = {"arguments": {"id": "employee-123"}}
result = employee_tool.execute(payload)

# Convert back to native dataclasses or dicts as needed
print(result.data)
Both execution styles accept an optional options keyword to pass metadata that is not forwarded to the StackOne API. The Python SDK uses this to power telemetry features such as LangSmith implicit feedback streams:
employee_tool.call(
    id="employee-123",
    options={
        "feedback_session_id": "chat-42",
        "feedback_user_id": "user-123",
        "feedback_metadata": {"conversation_id": "abc"},
    },
)
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}")
Discover relevant tools at runtime using natural language queries:
# Search for tools by intent
tools = toolset.search_tools(
    "manage employee records and time off",
    top_k=5,
    search="auto",  # tries semantic API first, falls back to local search
)

print(f"Found {len(tools)} tools")

# Use with any framework
openai_tools = tools.to_openai()
langchain_tools = tools.to_langchain()
See Tool Search for search modes, all three methods, and advanced usage.

Environment Configuration

import os
from stackone_ai import StackOneToolSet

# Set in your .env file
# STACKONE_API_KEY=your_api_key
# STACKONE_ACCOUNT_ID=your_account_id

toolset = StackOneToolSet(
    api_key=os.getenv('STACKONE_API_KEY')
)

# Use environment account ID as default
account_id = os.getenv('STACKONE_ACCOUNT_ID') or 'fallback-account-id'
from dotenv import load_dotenv
import os

# Load environment variables from .env file
load_dotenv()

from stackone_ai import StackOneToolSet

toolset = StackOneToolSet(
    api_key=os.getenv('STACKONE_API_KEY')
)

Implicit Feedback

The SDK can emit implicit behavioural signals to LangSmith whenever a tool is executed. Provide a LangSmith API key and optional overrides via environment variables:
LANGSMITH_API_KEY=your_langsmith_key
STACKONE_IMPLICIT_FEEDBACK_ENABLED=true  # defaults to true when an API key exists
STACKONE_IMPLICIT_FEEDBACK_PROJECT=stackone-agents
STACKONE_IMPLICIT_FEEDBACK_TAGS=python-sdk,stackone

Example

Next Steps